[PATCH 3/8] vinyl: do not use column mask as trigger for turning REPLACE into INSERT

Vladimir Davydov vdavydov.dev at gmail.com
Sun Oct 14 21:16:47 MSK 2018


If a REPLACE statement was generated by an UPDATE operation that updated
a column indexed by a secondary key, we can turn it into INSERT when the
secondary index is dumped, because there can't be an older statement
with the same key other than DELETE. Currently, we use the statement
column mask to detect such REPLACEs in the write iterator, but I'm
planning to get rid of vy_stmt_column_mask so let's instead introduce
a new statement flag to mark such REPLACEs.
---
 src/box/vinyl.c             |  3 +++
 src/box/vy_stmt.c           |  8 ++++++++
 src/box/vy_stmt.h           | 11 ++++++++++-
 src/box/vy_write_iterator.c |  5 ++---
 4 files changed, 23 insertions(+), 4 deletions(-)

diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index 869c4140..be21d9d9 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -1723,6 +1723,9 @@ vy_perform_update(struct vy_env *env, struct vy_tx *tx, struct txn_stmt *stmt,
 
 	if (vy_check_is_unique(env, tx, space, stmt->new_tuple) != 0)
 		return -1;
+
+	vy_stmt_set_flags(stmt->new_tuple, VY_STMT_UPDATE);
+
 	if (vy_tx_set(tx, pk, stmt->new_tuple) != 0)
 		return -1;
 	if (space->index_count == 1)
diff --git a/src/box/vy_stmt.c b/src/box/vy_stmt.c
index ebe64300..bb9e1edb 100644
--- a/src/box/vy_stmt.c
+++ b/src/box/vy_stmt.c
@@ -61,6 +61,14 @@ static inline uint8_t
 vy_stmt_persistent_flags(const struct tuple *stmt, bool is_primary)
 {
 	uint8_t mask = VY_STMT_FLAGS_ALL;
+
+	/*
+	 * This flag is only used by the write iterator to turn
+	 * in-memory REPLACEs into INSERTs on dump so no need to
+	 * persist it.
+	 */
+	mask &= ~VY_STMT_UPDATE;
+
 	if (!is_primary) {
 		/*
 		 * Do not store VY_STMT_DEFERRED_DELETE flag in
diff --git a/src/box/vy_stmt.h b/src/box/vy_stmt.h
index 73e18ca7..4a67b3c7 100644
--- a/src/box/vy_stmt.h
+++ b/src/box/vy_stmt.h
@@ -98,9 +98,18 @@ enum {
 	 */
 	VY_STMT_SKIP_READ		= 1 << 1,
 	/**
+	 * This flag is set for those REPLACE statements that were
+	 * generated by UPDATE operations. It is used by the write
+	 * iterator to turn such REPLACEs into INSERTs in secondary
+	 * indexes so that they can get annihilated with DELETEs on
+	 * compaction. It is never written to disk.
+	 */
+	VY_STMT_UPDATE			= 1 << 2,
+	/**
 	 * Bit mask of all statement flags.
 	 */
-	VY_STMT_FLAGS_ALL = VY_STMT_DEFERRED_DELETE | VY_STMT_SKIP_READ,
+	VY_STMT_FLAGS_ALL = (VY_STMT_DEFERRED_DELETE | VY_STMT_SKIP_READ |
+			     VY_STMT_UPDATE),
 };
 
 /**
diff --git a/src/box/vy_write_iterator.c b/src/box/vy_write_iterator.c
index 17b80685..0b6ab0a8 100644
--- a/src/box/vy_write_iterator.c
+++ b/src/box/vy_write_iterator.c
@@ -694,14 +694,13 @@ vy_write_iterator_build_history(struct vy_write_iterator *stream,
 		*is_first_insert = vy_stmt_type(src->tuple) == IPROTO_INSERT;
 
 		if (!stream->is_primary &&
-		    vy_stmt_type(src->tuple) == IPROTO_REPLACE) {
+		    (vy_stmt_flags(src->tuple) & VY_STMT_UPDATE) != 0) {
 			/*
 			 * If a REPLACE stored in a secondary index was
 			 * generated by an update operation, it can be
 			 * turned into an INSERT.
 			 */
-			if (vy_stmt_column_mask(src->tuple) != UINT64_MAX)
-				*is_first_insert = true;
+			*is_first_insert = true;
 		}
 
 		/*
-- 
2.11.0




More information about the Tarantool-patches mailing list