[PATCH v2 2/2] vinyl: implement space.bsize, index.bsize, and index.len

Vladimir Davydov vdavydov.dev at gmail.com
Sun Feb 11 14:12:56 MSK 2018


 - space.bsize returns the size of user data stored in the space.
   It is the sum of memory.bytes and disk.bytes as reported by
   the primary index.

 - index.bsize returns the size of memory used for indexing data.
   It is the sum of memory.index_size, disk.index_size, and
   disk.bloom_size as reported by index.info. For secondary indexes
   we also add the size of binary data stored on disk (disk.bytes),
   because it is only needed to build the index.

 - index.len returns the total number of rows stored in the index.
   It is the sum of memory.rows and disk.rows as reported by
   index.info. Note, it may be greater than the number of tuples
   stored in the space, because it includes DELETE and UPDATE
   statements.

Closes #2863
Closes #3056
---
 src/box/vinyl.c                |  42 +++++++-
 test/vinyl/constraint.result   |  16 ---
 test/vinyl/constraint.test.lua |   9 --
 test/vinyl/ddl.result          |  30 ------
 test/vinyl/ddl.test.lua        |  15 ---
 test/vinyl/info.result         | 219 +++++++++++++++++++++++++++++++++++++++++
 test/vinyl/info.test.lua       |  67 +++++++++++++
 7 files changed, 324 insertions(+), 74 deletions(-)

diff --git a/src/box/vinyl.c b/src/box/vinyl.c
index 568ca17e..94d0d038 100644
--- a/src/box/vinyl.c
+++ b/src/box/vinyl.c
@@ -1200,15 +1200,49 @@ vinyl_space_build_secondary_key(struct space *old_space,
 static size_t
 vinyl_space_bsize(struct space *space)
 {
-	(void)space;
-	return 0;
+	/*
+	 * Return the sum size of user data this space
+	 * accommodates. Since full tuples are stored in
+	 * primary indexes, it is basically the size of
+	 * binary data stored in this space's primary index.
+	 */
+	struct index *pk_base = space_index(space, 0);
+	if (pk_base == NULL)
+		return 0;
+	struct vy_index *pk = vy_index(pk_base);
+	return pk->stat.memory.count.bytes + pk->stat.disk.count.bytes;
+}
+
+static ssize_t
+vinyl_index_size(struct index *base)
+{
+	/*
+	 * Return the total number of statements in the index.
+	 * Note, it may be greater than the number of tuples
+	 * actually stored in the space, but it should be a
+	 * fairly good estimate.
+	 */
+	struct vy_index *index = vy_index(base);
+	return index->stat.memory.count.rows + index->stat.disk.count.rows;
 }
 
 static ssize_t
 vinyl_index_bsize(struct index *base)
 {
+	/*
+	 * Return the cost of indexing user data. For both
+	 * primary and secondary indexes, this includes the
+	 * size of page index, bloom filter, and memory tree
+	 * extents. For secondary indexes, we also add the
+	 * total size of statements stored on disk, because
+	 * they are only needed for building the index.
+	 */
 	struct vy_index *index = vy_index(base);
-	return index->stat.memory.count.bytes;
+	ssize_t bsize = vy_index_mem_tree_size(index) +
+		index->page_index_size + index->bloom_size;
+	if (index->id > 0)
+		bsize += index->stat.disk.count.bytes;
+	return bsize;
 }
 
 /* {{{ Public API of transaction control: start/end transaction,
@@ -4001,7 +4035,7 @@ static const struct index_vtab vinyl_index_vtab = {
 	/* .commit_create = */ vinyl_index_commit_create,
 	/* .commit_drop = */ vinyl_index_commit_drop,
 	/* .update_def = */ generic_index_update_def,
-	/* .size = */ generic_index_size,
+	/* .size = */ vinyl_index_size,
 	/* .bsize = */ vinyl_index_bsize,
 	/* .min = */ generic_index_min,
 	/* .max = */ generic_index_max,
diff --git a/test/vinyl/constraint.result b/test/vinyl/constraint.result
index 4c9807b8..46ed1c9e 100644
--- a/test/vinyl/constraint.result
+++ b/test/vinyl/constraint.result
@@ -142,19 +142,3 @@ space = nil
 pk = nil
 ---
 ...
--------------------------------------------------------------------------------
--- space:len() is unsupported
--------------------------------------------------------------------------------
-space = box.schema.space.create('test_len', { engine = 'vinyl' })
----
-...
-_ = space:create_index('primary', { type = 'tree', parts = {1, 'string'}})
----
-...
-space:len()
----
-- error: Index 'primary' (TREE) of space 'test_len' (vinyl) does not support size()
-...
-space:drop()
----
-...
diff --git a/test/vinyl/constraint.test.lua b/test/vinyl/constraint.test.lua
index bdfa3780..4a785f7b 100644
--- a/test/vinyl/constraint.test.lua
+++ b/test/vinyl/constraint.test.lua
@@ -49,12 +49,3 @@ t3 = space:insert({string.rep('x', 102200)})
 space:drop()
 space = nil
 pk = nil
-
--------------------------------------------------------------------------------
--- space:len() is unsupported
--------------------------------------------------------------------------------
-
-space = box.schema.space.create('test_len', { engine = 'vinyl' })
-_ = space:create_index('primary', { type = 'tree', parts = {1, 'string'}})
-space:len()
-space:drop()
diff --git a/test/vinyl/ddl.result b/test/vinyl/ddl.result
index 9fa3504c..45a38344 100644
--- a/test/vinyl/ddl.result
+++ b/test/vinyl/ddl.result
@@ -229,36 +229,6 @@ space:drop()
 ---
 ...
 --
--- gh-1632: index:bsize()
---
-space = box.schema.space.create('test', { engine = 'vinyl' })
----
-...
-pk = space:create_index('primary', { type = 'tree', parts = {1, 'unsigned'}  })
----
-...
-for i=1,10 do box.space.test:replace({i}) end
----
-...
-box.space.test.index.primary:bsize() > 0
----
-- true
-...
-box.snapshot()
----
-- ok
-...
-while space.index.primary:info().run_count ~= 1 do fiber.sleep(0.01) end
----
-...
-box.space.test.index.primary:bsize() == 0
----
-- true
-...
-space:drop()
----
-...
---
 -- gh-1709: need error on altering space
 --
 space = box.schema.space.create('test', {engine='vinyl'})
diff --git a/test/vinyl/ddl.test.lua b/test/vinyl/ddl.test.lua
index bb9e5596..53205df9 100644
--- a/test/vinyl/ddl.test.lua
+++ b/test/vinyl/ddl.test.lua
@@ -85,21 +85,6 @@ space.index.primary:alter({parts = {1, 'unsigned', 2, 'unsigned'}})
 space:drop()
 
 --
--- gh-1632: index:bsize()
---
-space = box.schema.space.create('test', { engine = 'vinyl' })
-pk = space:create_index('primary', { type = 'tree', parts = {1, 'unsigned'}  })
-for i=1,10 do box.space.test:replace({i}) end
-box.space.test.index.primary:bsize() > 0
-
-box.snapshot()
-while space.index.primary:info().run_count ~= 1 do fiber.sleep(0.01) end
-
-box.space.test.index.primary:bsize() == 0
-
-space:drop()
-
---
 -- gh-1709: need error on altering space
 --
 space = box.schema.space.create('test', {engine='vinyl'})
diff --git a/test/vinyl/info.result b/test/vinyl/info.result
index 2724cc3d..35404f9d 100644
--- a/test/vinyl/info.result
+++ b/test/vinyl/info.result
@@ -912,6 +912,225 @@ stat_diff(gstat(), st, 'tx')
 ---
 - commit: 1
 ...
+s:drop()
+---
+...
+--
+-- space.bsize, index.len, index.bsize
+--
+s = box.schema.space.create('test', {engine = 'vinyl'})
+---
+...
+s:bsize()
+---
+- 0
+...
+i1 = s:create_index('i1', {parts = {1, 'unsigned'}, run_count_per_level = 1})
+---
+...
+i2 = s:create_index('i2', {parts = {2, 'unsigned'}, run_count_per_level = 1})
+---
+...
+s:bsize()
+---
+- 0
+...
+i1:len(), i2:len()
+---
+- 0
+- 0
+...
+i1:bsize(), i2:bsize()
+---
+- 0
+- 0
+...
+for i = 1, 100, 2 do s:replace{i, i, pad()} end
+---
+...
+st1 = i1:info()
+---
+...
+st2 = i2:info()
+---
+...
+s:bsize()
+---
+- 53300
+...
+i1:len(), i2:len()
+---
+- 50
+- 50
+...
+i1:bsize(), i2:bsize()
+---
+- 49152
+- 49152
+...
+s:bsize() == st1.memory.bytes
+---
+- true
+...
+i1:len() == st1.memory.rows
+---
+- true
+...
+i2:len() == st2.memory.rows
+---
+- true
+...
+i1:bsize() == st1.memory.index_size
+---
+- true
+...
+i2:bsize() == st2.memory.index_size
+---
+- true
+...
+box.snapshot()
+---
+- ok
+...
+st1 = i1:info()
+---
+...
+st2 = i2:info()
+---
+...
+s:bsize()
+---
+- 52199
+...
+i1:len(), i2:len()
+---
+- 50
+- 50
+...
+i1:bsize(), i2:bsize()
+---
+- 4390
+- 4946
+...
+s:bsize() == st1.disk.bytes
+---
+- true
+...
+i1:len() == st1.disk.rows
+---
+- true
+...
+i2:len() == st2.disk.rows
+---
+- true
+...
+i1:bsize() == st1.disk.index_size + st1.disk.bloom_size
+---
+- true
+...
+i2:bsize() == st2.disk.index_size + st2.disk.bloom_size + st2.disk.bytes
+---
+- true
+...
+for i = 1, 100, 2 do s:delete(i) end
+---
+...
+for i = 2, 100, 2 do s:replace{i, i, pad()} end
+---
+...
+st1 = i1:info()
+---
+...
+st2 = i2:info()
+---
+...
+s:bsize()
+---
+- 107449
+...
+i1:len(), i2:len()
+---
+- 150
+- 150
+...
+i1:bsize(), i2:bsize()
+---
+- 53542
+- 54098
+...
+s:bsize() == st1.memory.bytes + st1.disk.bytes
+---
+- true
+...
+i1:len() == st1.memory.rows + st1.disk.rows
+---
+- true
+...
+i2:len() == st2.memory.rows + st2.disk.rows
+---
+- true
+...
+i1:bsize() == st1.memory.index_size + st1.disk.index_size + st1.disk.bloom_size
+---
+- true
+...
+i2:bsize() == st2.memory.index_size + st2.disk.index_size + st2.disk.bloom_size + st2.disk.bytes
+---
+- true
+...
+box.snapshot()
+---
+- ok
+...
+wait(function() return i1:info() end, st1, 'disk.compact.count', 1)
+---
+...
+wait(function() return i2:info() end, st2, 'disk.compact.count', 1)
+---
+...
+st1 = i1:info()
+---
+...
+st2 = i2:info()
+---
+...
+s:bsize()
+---
+- 52199
+...
+i1:len(), i2:len()
+---
+- 50
+- 50
+...
+i1:bsize(), i2:bsize()
+---
+- 4390
+- 4946
+...
+s:bsize() == st1.disk.bytes
+---
+- true
+...
+i1:len() == st1.disk.rows
+---
+- true
+...
+i2:len() == st2.disk.rows
+---
+- true
+...
+i1:bsize() == st1.disk.index_size + st1.disk.bloom_size
+---
+- true
+...
+i2:bsize() == st2.disk.index_size + st2.disk.bloom_size + st2.disk.bytes
+---
+- true
+...
+s:drop()
+---
+...
 test_run:cmd('switch default')
 ---
 - true
diff --git a/test/vinyl/info.test.lua b/test/vinyl/info.test.lua
index b1c9bd5f..1da74ca9 100644
--- a/test/vinyl/info.test.lua
+++ b/test/vinyl/info.test.lua
@@ -309,6 +309,73 @@ stat_diff(gstat(), st, 'tx')
 box.commit()
 stat_diff(gstat(), st, 'tx')
 
+s:drop()
+
+--
+-- space.bsize, index.len, index.bsize
+--
+
+s = box.schema.space.create('test', {engine = 'vinyl'})
+s:bsize()
+i1 = s:create_index('i1', {parts = {1, 'unsigned'}, run_count_per_level = 1})
+i2 = s:create_index('i2', {parts = {2, 'unsigned'}, run_count_per_level = 1})
+s:bsize()
+i1:len(), i2:len()
+i1:bsize(), i2:bsize()
+
+for i = 1, 100, 2 do s:replace{i, i, pad()} end
+st1 = i1:info()
+st2 = i2:info()
+s:bsize()
+i1:len(), i2:len()
+i1:bsize(), i2:bsize()
+s:bsize() == st1.memory.bytes
+i1:len() == st1.memory.rows
+i2:len() == st2.memory.rows
+i1:bsize() == st1.memory.index_size
+i2:bsize() == st2.memory.index_size
+
+box.snapshot()
+st1 = i1:info()
+st2 = i2:info()
+s:bsize()
+i1:len(), i2:len()
+i1:bsize(), i2:bsize()
+s:bsize() == st1.disk.bytes
+i1:len() == st1.disk.rows
+i2:len() == st2.disk.rows
+i1:bsize() == st1.disk.index_size + st1.disk.bloom_size
+i2:bsize() == st2.disk.index_size + st2.disk.bloom_size + st2.disk.bytes
+
+for i = 1, 100, 2 do s:delete(i) end
+for i = 2, 100, 2 do s:replace{i, i, pad()} end
+st1 = i1:info()
+st2 = i2:info()
+s:bsize()
+i1:len(), i2:len()
+i1:bsize(), i2:bsize()
+s:bsize() == st1.memory.bytes + st1.disk.bytes
+i1:len() == st1.memory.rows + st1.disk.rows
+i2:len() == st2.memory.rows + st2.disk.rows
+i1:bsize() == st1.memory.index_size + st1.disk.index_size + st1.disk.bloom_size
+i2:bsize() == st2.memory.index_size + st2.disk.index_size + st2.disk.bloom_size + st2.disk.bytes
+
+box.snapshot()
+wait(function() return i1:info() end, st1, 'disk.compact.count', 1)
+wait(function() return i2:info() end, st2, 'disk.compact.count', 1)
+st1 = i1:info()
+st2 = i2:info()
+s:bsize()
+i1:len(), i2:len()
+i1:bsize(), i2:bsize()
+s:bsize() == st1.disk.bytes
+i1:len() == st1.disk.rows
+i2:len() == st2.disk.rows
+i1:bsize() == st1.disk.index_size + st1.disk.bloom_size
+i2:bsize() == st2.disk.index_size + st2.disk.bloom_size + st2.disk.bytes
+
+s:drop()
+
 test_run:cmd('switch default')
 test_run:cmd('stop server test')
 test_run:cmd('cleanup server test')
-- 
2.11.0




More information about the Tarantool-patches mailing list