[PATCH] vinyl: don't check key uniqueness if indexed fields are not updated

Vladimir Davydov vdavydov.dev at gmail.com
Tue Feb 6 16:56:42 MSK 2018


We can save a lookup in a secondary index on update if indexed fields
are not modified. The extra check comes for free as we have a bit mask
of all updated fields.

Closes #2980
---
Branch: gh-2980-vy-dont-check-unique-if-not-updated

 src/box/vinyl.c                     |  2 ++
 test/vinyl/update_optimize.result   | 68 +++++++++++++++++++++++++++++++++++++
 test/vinyl/update_optimize.test.lua | 32 +++++++++++++++++
 3 files changed, 102 insertions(+)

diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index b2331081..d69d5177 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -1373,6 +1373,8 @@ vy_insert_secondary(struct vy_env *env, struct vy_tx *tx, struct space *space,
 	 * unique a conflict is impossible.
 	 */
 	if (index->opts.is_unique &&
+	    !key_update_can_be_skipped(index->key_def->column_mask,
+				       vy_stmt_column_mask(stmt)) &&
 	    (!index->key_def->is_nullable ||
 	     !vy_tuple_key_contains_null(stmt, index->key_def))) {
 		struct tuple *key = vy_stmt_extract_key(stmt, index->key_def,
diff --git a/test/vinyl/update_optimize.result b/test/vinyl/update_optimize.result
index f4e05755..fbd42df0 100644
--- a/test/vinyl/update_optimize.result
+++ b/test/vinyl/update_optimize.result
@@ -640,6 +640,74 @@ index3:select{}
   - [10, 100, 1000, 10000, 100000, 1]
   - [20, 200, 2000, 20000, 200000, 2]
 ...
+--
+-- gh-2980: key uniqueness is not checked if indexed fields
+-- are not updated.
+--
+space:truncate()
+---
+...
+space:replace{1, 1, 1, 1, 1}
+---
+- [1, 1, 1, 1, 1]
+...
+LOOKUPS_BASE = {0, 0, 0}
+---
+...
+test_run:cmd("setopt delimiter ';'")
+---
+- true
+...
+function lookups()
+    local ret = {}
+    for i = 1, #LOOKUPS_BASE do
+        local info = space.index[i - 1]:info()
+        table.insert(ret, info.lookup - LOOKUPS_BASE[i])
+    end
+    return ret
+end;
+---
+...
+test_run:cmd("setopt delimiter ''");
+---
+- true
+...
+LOOKUPS_BASE = lookups()
+---
+...
+-- update of a field that is not indexed
+space:update(1, {{'+', 1, 1}})
+---
+- [2, 1, 1, 1, 1]
+...
+lookups()
+---
+- - 1
+  - 0
+  - 0
+...
+-- update of a field indexed by space.index[1]
+space:update(1, {{'+', 3, 1}})
+---
+- [2, 1, 2, 1, 1]
+...
+lookups()
+---
+- - 2
+  - 1
+  - 0
+...
+-- update of a field indexed by space.index[2]
+space:update(1, {{'+', 5, 1}})
+---
+- [2, 1, 2, 1, 2]
+...
+lookups()
+---
+- - 3
+  - 1
+  - 1
+...
 space:drop()
 ---
 ...
diff --git a/test/vinyl/update_optimize.test.lua b/test/vinyl/update_optimize.test.lua
index a1bdfb9a..32144172 100644
--- a/test/vinyl/update_optimize.test.lua
+++ b/test/vinyl/update_optimize.test.lua
@@ -201,4 +201,36 @@ index:select{}
 index2:select{}
 index3:select{}
 
+--
+-- gh-2980: key uniqueness is not checked if indexed fields
+-- are not updated.
+--
+space:truncate()
+space:replace{1, 1, 1, 1, 1}
+
+LOOKUPS_BASE = {0, 0, 0}
+test_run:cmd("setopt delimiter ';'")
+function lookups()
+    local ret = {}
+    for i = 1, #LOOKUPS_BASE do
+        local info = space.index[i - 1]:info()
+        table.insert(ret, info.lookup - LOOKUPS_BASE[i])
+    end
+    return ret
+end;
+test_run:cmd("setopt delimiter ''");
+LOOKUPS_BASE = lookups()
+
+-- update of a field that is not indexed
+space:update(1, {{'+', 1, 1}})
+lookups()
+
+-- update of a field indexed by space.index[1]
+space:update(1, {{'+', 3, 1}})
+lookups()
+
+-- update of a field indexed by space.index[2]
+space:update(1, {{'+', 5, 1}})
+lookups()
+
 space:drop()
-- 
2.11.0




More information about the Tarantool-patches mailing list