From a66553900e9e1d719a8fa2c6724534a472ea69ba Mon Sep 17 00:00:00 2001 From: Natalia Ogoreltseva Date: Fri, 19 Feb 2021 18:17:02 +0300 Subject: [PATCH 1/7] gh-1691 create an overview page about indexes --- doc/book/box/data_model.rst | 251 +--------- doc/book/box/indexes.rst | 467 ++++++++++++++++-- .../reference_lua/box_index/select.rst | 50 -- .../reference_lua/box_space/create_index.rst | 16 +- 4 files changed, 472 insertions(+), 312 deletions(-) diff --git a/doc/book/box/data_model.rst b/doc/book/box/data_model.rst index 67bd4aaf5e..30b0d5c800 100644 --- a/doc/book/box/data_model.rst +++ b/doc/book/box/data_model.rst @@ -61,11 +61,34 @@ When Tarantool returns a tuple value in the console, by default it uses :ref:`YAML ` format, for example: ``[3, 'Ace of Base', 1993]``. -.. // Including a section about indexes - .. _index-box_index: -.. include:: indexes.rst +-------------------------------------------------------------------------------- +Indexes +-------------------------------------------------------------------------------- + +Read the full information about indexes on page :doc:`Indexes `. + +An **index** is a group of key values and pointers. + +As with spaces, you should specify the index **name**, and let Tarantool +come up with a unique **numeric identifier** ("index id"). + +An index always has a **type**. The default index type is 'TREE'. +TREE indexes are provided by all Tarantool engines, can index unique and +non-unique values, support partial key searches, comparisons and ordered results. +Additionally, memtx engine supports HASH, RTREE and BITSET indexes. + +An index may be **multi-part**, that is, you can declare that an index key value +is composed of two or more fields in the tuple, in any order. +For example, for an ordinary TREE index, the maximum number of parts is 255. + +An index may be **unique**, that is, you can declare that it would be illegal +to have the same key value twice. + +The first index defined on a space is called the **primary key index**, +and it must be unique. All other indexes are called **secondary indexes**, +and they may be non-unique. .. _index-box_data-types: @@ -792,228 +815,6 @@ See reference on ``box.space`` for more The client server protocol is open and documented. See this :ref:`annotated BNF `. -.. _index-box_index-operations: - -******************************************************** -Index operations -******************************************************** - -Index operations are automatic: if a data-manipulation request changes a tuple, -then it also changes the index keys defined for the tuple. - -The simple index-creation operation that we've illustrated before is: - -.. cssclass:: highlight -.. parsed-literal:: - - :samp:`box.space.{space-name}:create_index('{index-name}')` - -This creates a unique TREE index on the first field of all tuples -(often called "Field#1"), which is assumed to be numeric. - -The simple SELECT request that we've illustrated before is: - -.. cssclass:: highlight -.. parsed-literal:: - - :extsamp:`box.space.{*{space-name}*}:select({*{value}*})` - -This looks for a single tuple via the first index. Since the first index -is always unique, the maximum number of returned tuples will be: one. -You can call ``select()`` without arguments, causing all tuples to be returned. - -Let's continue working with the space 'tester' created in the :ref:`"Getting -started" exercises ` but first modify it: - -.. code-block:: tarantoolsession - - tarantool> box.space.tester:format({ - > {name = 'id', type = 'unsigned'}, - > {name = 'band_name', type = 'string'}, - > {name = 'year', type = 'unsigned'}, - > {name = 'rate', type = 'unsigned', is_nullable=true}}) - --- - ... - -Add the rate to the tuple #1 and #2: - -.. code-block:: tarantoolsession - - tarantool> box.space.tester:update(1, {{'=', 4, 5}}) - --- - - [1, 'Roxette', 1986, 5] - ... - tarantool> box.space.tester:update(2, {{'=', 4, 4}}) - --- - - [2, 'Scorpions', 2015, 4] - ... - - -And insert another tuple: - -.. code-block:: tarantoolsession - - tarantool> box.space.tester:insert({4, 'Roxette', 2016, 3}) - --- - - [4, 'Roxette', 2016, 3] - ... - -**The existing SELECT variations:** - -1. The search can use comparisons other than equality. - -.. code-block:: tarantoolsession - - tarantool> box.space.tester:select(1, {iterator = 'GT'}) - --- - - - [2, 'Scorpions', 2015, 4] - - [3, 'Ace of Base', 1993] - - [4, 'Roxette', 2016, 3] - ... - -The :ref:`comparison operators ` are LT, LE, EQ, REQ, GE, GT -(for "less than", "less than or equal", "equal", "reversed equal", -"greater than or equal", "greater than" respectively). -Comparisons make sense if and only if the index type is ‘TREE'. - -This type of search may return more than one tuple; if so, the tuples will be -in descending order by key when the comparison operator is LT or LE or REQ, -otherwise in ascending order. - -2. The search can use a secondary index. - -For a primary-key search, it is optional to specify an index name. -For a secondary-key search, it is mandatory. - -.. code-block:: tarantoolsession - - tarantool> box.space.tester:create_index('secondary', {parts = {{field=3, type='unsigned'}}}) - --- - - unique: true - parts: - - type: unsigned - is_nullable: false - fieldno: 3 - id: 2 - space_id: 512 - type: TREE - name: secondary - ... - tarantool> box.space.tester.index.secondary:select({1993}) - --- - - - [3, 'Ace of Base', 1993] - ... - -3. The search may be for some key parts starting with the prefix of - the key. Notice that partial key searches are available only in TREE indexes. - -.. code-block:: tarantoolsession - - -- Create an index with three parts - tarantool> box.space.tester:create_index('tertiary', {parts = {{field = 2, type = 'string'}, {field=3, type='unsigned'}, {field=4, type='unsigned'}}}) - --- - - unique: true - parts: - - type: string - is_nullable: false - fieldno: 2 - - type: unsigned - is_nullable: false - fieldno: 3 - - type: unsigned - is_nullable: true - fieldno: 4 - id: 6 - space_id: 513 - type: TREE - name: tertiary - ... - -- Make a partial search - tarantool> box.space.tester.index.tertiary:select({'Scorpions', 2015}) - --- - - - [2, 'Scorpions', 2015, 4] - ... - -4. The search may be for all fields, using a table for the value: - -.. code-block:: tarantoolsession - - tarantool> box.space.tester.index.tertiary:select({'Roxette', 2016, 3}) - --- - - - [4, 'Roxette', 2016, 3] - ... - -or the search can be for one field, using a table or a scalar: - -.. code-block:: tarantoolsession - - tarantool> box.space.tester.index.tertiary:select({'Roxette'}) - --- - - - [1, 'Roxette', 1986, 5] - - [4, 'Roxette', 2016, 3] - ... - -******************************************************** -Working with BITSET and RTREE -******************************************************** - -**BITSET example:** - -.. code-block:: tarantoolsession - - tarantool> box.schema.space.create('bitset_example') - tarantool> box.space.bitset_example:create_index('primary') - tarantool> box.space.bitset_example:create_index('bitset',{unique=false,type='BITSET', parts={2,'unsigned'}}) - tarantool> box.space.bitset_example:insert{1,1} - tarantool> box.space.bitset_example:insert{2,4} - tarantool> box.space.bitset_example:insert{3,7} - tarantool> box.space.bitset_example:insert{4,3} - tarantool> box.space.bitset_example.index.bitset:select(2, {iterator='BITS_ANY_SET'}) - -The result will be: - -.. code-block:: tarantoolsession - - --- - - - [3, 7] - - [4, 3] - ... - -because (7 AND 2) is not equal to 0, and (3 AND 2) is not equal to 0. - -**RTREE example:** - -.. code-block:: tarantoolsession - - tarantool> box.schema.space.create('rtree_example') - tarantool> box.space.rtree_example:create_index('primary') - tarantool> box.space.rtree_example:create_index('rtree',{unique=false,type='RTREE', parts={2,'ARRAY'}}) - tarantool> box.space.rtree_example:insert{1, {3, 5, 9, 10}} - tarantool> box.space.rtree_example:insert{2, {10, 11}} - tarantool> box.space.rtree_example.index.rtree:select({4, 7, 5, 9}, {iterator = 'GT'}) - -The result will be: - -.. code-block:: tarantoolsession - - --- - - - [1, [3, 5, 9, 10]] - ... - -because a rectangle whose corners are at coordinates ``4,7,5,9`` is entirely -within a rectangle whose corners are at coordinates ``3,5,9,10``. - -Additionally, there exist -:doc:`index iterator operations `. -They can only be used with code in Lua and C/C++. Index iterators are for -traversing indexes one key at a time, taking advantage of features that are -specific to an index type, for example evaluating Boolean expressions when -traversing BITSET indexes, or going in descending order when traversing TREE indexes. - -See also other index operations like -:doc:`alter() ` -(modify index) and :doc:`drop() ` -(delete index) in reference for :doc:`/reference/reference_lua/box_index`. ******************************************************** Complexity factors diff --git a/doc/book/box/indexes.rst b/doc/book/box/indexes.rst index 068f54da2c..6438ea6b18 100644 --- a/doc/book/box/indexes.rst +++ b/doc/book/box/indexes.rst @@ -1,18 +1,14 @@ --------------------------------------------------------------------------------- +================================================================================ Indexes --------------------------------------------------------------------------------- +================================================================================ -An **index** is a group of key values and pointers. +An **index** is special data structure that stores a group of key values and +pointers. It is used for efficient manipulations with data. As with spaces, you should specify the index **name**, and let Tarantool come up with a unique **numeric identifier** ("index id"). -An index always has a **type**. The default index type is 'TREE'. -TREE indexes are provided by all Tarantool engines, can index unique and -non-unique values, support partial key searches, comparisons and ordered results. -Additionally, memtx engine supports HASH, RTREE and BITSET indexes. - An index may be **multi-part**, that is, you can declare that an index key value is composed of two or more fields in the tuple, in any order. For example, for an ordinary TREE index, the maximum number of parts is 255. @@ -24,46 +20,459 @@ The first index defined on a space is called the **primary key index**, and it must be unique. All other indexes are called **secondary indexes**, and they may be non-unique. +Indexes have certain limitations. See details on page +:doc:`Limitations `. + +-------------------------------------------------------------------------------- +Creating an index +-------------------------------------------------------------------------------- + An index definition may include identifiers of tuple fields and their expected -**types**. See allowed indexed field types -:ref:`here `. +**types**. See allowed indexed field types in section +:ref:`Details about indexed field types `. -.. NOTE:: +.. NOTE:: - A recommended design pattern for a data model is to base primary keys on the - first fields of a tuple, because this speeds up tuple comparison. + A recommended design pattern for a data model is to base primary keys on the + first fields of a tuple, because this speeds up tuple comparison. -In our example, we first defined the primary index (named 'primary') based on -field #1 of each tuple: +Let's look on an example where we first define the primary index (named 'primary') +based on field #1 of each tuple: -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession - tarantool> i = s:create_index('primary', {type = 'hash', parts = {{field = 1, type = 'unsigned'}}} + tarantool> i = s:create_index('primary', {type = 'hash', parts = {{field = 1, type = 'unsigned'}}} The effect is that, for all tuples in space 'tester', field #1 must exist and must contain an unsigned integer. -The index type is 'hash', so values in field #1 must be unique, because keys +The index type is HASH, so values in field #1 must be unique, because keys in HASH indexes are unique. -After that, we defined a secondary index (named 'secondary') based on field #2 +After that, let's define a secondary index (named 'secondary') based on field #2 of each tuple: -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession - tarantool> i = s:create_index('secondary', {type = 'tree', parts = {field = 2, type = 'string'}}) + tarantool> i = s:create_index('secondary', {type = 'tree', parts = {field = 2, type = 'string'}}) The effect is that, for all tuples in space 'tester', field #2 must exist and must contain a string. -The index type is 'tree', so values in field #2 must not be unique, because keys +The index type is TREE, so values in field #2 must not be unique, because keys in TREE indexes may be non-unique. -.. NOTE:: +Space definitions and index definitions are stored permanently in Tarantool's +system spaces :ref:`_space ` and :ref:`_index ` +(for details, see reference on :ref:`box.space ` submodule). + +.. admonition:: Tip + :class: fact + + The full information about creating an index is in section + :doc:`/reference/reference_lua/box_space/create_index`. + +-------------------------------------------------------------------------------- +Index types +-------------------------------------------------------------------------------- + +An index always has a **type**. Different types are intended for different +usage scenarios. + +We give an overview of index features in the following table: + +.. container:: table + + .. list-table:: + :header-rows: 1 + + * - Feature + - TREE + - HASH + - RTREE + - BITSET + + * - unique + - \+ + - \+ + - \- + - \- + + * - non-unique + - \+ + - \- + - \+ + - \+ + + * - :ref:`is_nullable ` + - \+ + - \- + - \- + - \- + + * - multi-part + - \+ + - \+ + - \- + - \- + + * - :ref:`multikey ` + - \+ + - \- + - \- + - \- + + * - :ref:`partial-key search ` + - \+ + - \- + - \- + - \- + + * - updates + - \+ + - \+ + - \- + - \- + + * - deletes + - \+ + - \+ + - \- + - \- + + * - exclude_null (version 2.8+) + - \+ + - \- + - \- + - \- + + * - :doc:`iterator types ` + - ALL, EQ, REQ, GT, GE, LT, LE + - ALL, EQ, GT + - ALL, EQ, GT, GE, LT, LE, OVERLAPS, NEIGHBOR + - ALL, EQ, BITS_ALL_SET, BITS_ANY_SET, BITS_ALL_NOT_SET + +******************************************************************************** +TREE indexes +******************************************************************************** + +The default index type is 'TREE'. +TREE indexes are provided by memtx and vinyl engines, can index unique and +non-unique values, support partial key searches, comparisons and ordered results. + +This is a universal type of indexes, for most cases it will be the best choice. + +Additionally, memtx engine supports HASH, RTREE and BITSET indexes. + +******************************************************************************** +HASH indexes +******************************************************************************** + +HASH indexes require unique fields and loses to TREE in almost all respects. +So we do not recommend to use it in the applications. +HASH is now present in Tarantool mainly because of backward compatibility. + +Here are some tips. Do not use HASH index: + +* just if you want to +* if you think that HASH is faster with no performance metering +* if you want to iterate over the data +* for primary key +* as an only index + +Use HASH index: + +* if it is a secondary key +* if you 100% won't need to make it non-unique +* if you really need that 2-5% performance improvement +* if you have taken measurements on your data and you see this increase in performance +* if you save every byte on tuples (HASH is a little more compact) + +******************************************************************************** +RTREE indexes +******************************************************************************** + +RTREE is a multidimensional index supporting up to 32 number of dimensions. +It is used especially for indexing spacial information, such as geographical +objects. In :ref:`this example ` +we demonstrate spacial searches via RTREE index. + +RTREE index can accept two types of ``distance`` functions: +``euclid`` and ``manhattan``. + +**Example:** + +.. code-block:: tarantoolsession + + tarantool> box.schema.space.create('rtree_example') + tarantool> box.space.rtree_example:create_index('primary') + tarantool> box.space.rtree_example:create_index('rtree',{unique=false,type='RTREE', parts={2,'ARRAY'}}) + tarantool> box.space.rtree_example:insert{1, {3, 5, 9, 10}} + tarantool> box.space.rtree_example:insert{2, {10, 11}} + tarantool> box.space.rtree_example.index.rtree:select({4, 7, 5, 9}, {iterator = 'GT'}) + +The result will be: + +.. code-block:: tarantoolsession + + --- + - - [1, [3, 5, 9, 10]] + ... + +because a rectangle whose corners are at coordinates ``4,7,5,9`` is entirely +within a rectangle whose corners are at coordinates ``3,5,9,10``. + +******************************************************************************** +BITSET indexes +******************************************************************************** + +Bitset is a bit mask. You should use it when you need to search by bit masks. +This can be, for example, storing a vector of attributes and search by these attributes. + +**Example 1:** + +The following script shows creation and search with a BITSET index. +Notice that BITSET cannot be unique, so first a primary-key index is created, +and bit values are entered as hexadecimal literals for easier reading. + +.. code-block:: tarantoolsession + + tarantool> s = box.schema.space.create('space_with_bitset') + tarantool> s:create_index('primary_index', { + > parts = {1, 'string'}, + > unique = true, + > type = 'TREE' + > }) + tarantool> s:create_index('bitset_index', { + > parts = {2, 'unsigned'}, + > unique = false, + > type = 'BITSET' + > }) + tarantool> s:insert{'Tuple with bit value = 01', 0x01} + tarantool> s:insert{'Tuple with bit value = 10', 0x02} + tarantool> s:insert{'Tuple with bit value = 11', 0x03} + tarantool> s.index.bitset_index:select(0x02, { + > iterator = box.index.EQ + > }) + --- + - - ['Tuple with bit value = 10', 2] + ... + tarantool> s.index.bitset_index:select(0x02, { + > iterator = box.index.BITS_ANY_SET + > }) + --- + - - ['Tuple with bit value = 10', 2] + - ['Tuple with bit value = 11', 3] + ... + tarantool> s.index.bitset_index:select(0x02, { + > iterator = box.index.BITS_ALL_SET + > }) + --- + - - ['Tuple with bit value = 10', 2] + - ['Tuple with bit value = 11', 3] + ... + tarantool> s.index.bitset_index:select(0x02, { + > iterator = box.index.BITS_ALL_NOT_SET + > }) + --- + - - ['Tuple with bit value = 01', 1] + ... + +**Example 2:** + +.. code-block:: tarantoolsession + + tarantool> box.schema.space.create('bitset_example') + tarantool> box.space.bitset_example:create_index('primary') + tarantool> box.space.bitset_example:create_index('bitset',{unique=false,type='BITSET', parts={2,'unsigned'}}) + tarantool> box.space.bitset_example:insert{1,1} + tarantool> box.space.bitset_example:insert{2,4} + tarantool> box.space.bitset_example:insert{3,7} + tarantool> box.space.bitset_example:insert{4,3} + tarantool> box.space.bitset_example.index.bitset:select(2, {iterator='BITS_ANY_SET'}) + +The result will be: + +.. code-block:: tarantoolsession + + --- + - - [3, 7] + - [4, 3] + ... + +because (7 AND 2) is not equal to 0, and (3 AND 2) is not equal to 0. + +Additionally, there exist +:doc:`index iterator operations `. +They can only be used with code in Lua and C/C++. Index iterators are for +traversing indexes one key at a time, taking advantage of features that are +specific to an index type, for example evaluating Boolean expressions when +traversing BITSET indexes, or going in descending order when traversing TREE indexes. + +.. _index-box_index-operations: + +-------------------------------------------------------------------------------- +Index operations +-------------------------------------------------------------------------------- + +Index operations are automatic: if a data-manipulation request changes a tuple, +then it also changes the index keys defined for the tuple. + +The simple index-creation operation that we've illustrated before is: + +.. cssclass:: highlight +.. parsed-literal:: + + :samp:`box.space.{space-name}:create_index('{index-name}')` + +This creates a unique TREE index on the first field of all tuples +(often called "Field#1"), which is assumed to be numeric. + +The simple SELECT request that we've illustrated before is: + +.. cssclass:: highlight +.. parsed-literal:: + + :extsamp:`box.space.{*{space-name}*}:select({*{value}*})` + +This looks for a single tuple via the first index. Since the first index +is always unique, the maximum number of returned tuples will be: one. +You can call ``select()`` without arguments, causing all tuples to be returned. + +Let's continue working with the space 'tester' created in the :ref:`"Getting +started" exercises ` but first modify it: + +.. code-block:: tarantoolsession + + tarantool> box.space.tester:format({ + > {name = 'id', type = 'unsigned'}, + > {name = 'band_name', type = 'string'}, + > {name = 'year', type = 'unsigned'}, + > {name = 'rate', type = 'unsigned', is_nullable=true}}) + --- + ... + +Add the rate to the tuple #1 and #2: + +.. code-block:: tarantoolsession + + tarantool> box.space.tester:update(1, {{'=', 4, 5}}) + --- + - [1, 'Roxette', 1986, 5] + ... + tarantool> box.space.tester:update(2, {{'=', 4, 4}}) + --- + - [2, 'Scorpions', 2015, 4] + ... + + +And insert another tuple: + +.. code-block:: tarantoolsession + + tarantool> box.space.tester:insert({4, 'Roxette', 2016, 3}) + --- + - [4, 'Roxette', 2016, 3] + ... + +**The existing SELECT variations:** + +1. The search can use comparisons other than equality. + +.. code-block:: tarantoolsession + + tarantool> box.space.tester:select(1, {iterator = 'GT'}) + --- + - - [2, 'Scorpions', 2015, 4] + - [3, 'Ace of Base', 1993] + - [4, 'Roxette', 2016, 3] + ... + +The :ref:`comparison operators ` are LT, LE, EQ, REQ, GE, GT +(for "less than", "less than or equal", "equal", "reversed equal", +"greater than or equal", "greater than" respectively). +Comparisons make sense if and only if the index type is ‘TREE'. + +This type of search may return more than one tuple; if so, the tuples will be +in descending order by key when the comparison operator is LT or LE or REQ, +otherwise in ascending order. + +2. The search can use a secondary index. + +For a primary-key search, it is optional to specify an index name. +For a secondary-key search, it is mandatory. + +.. code-block:: tarantoolsession + + tarantool> box.space.tester:create_index('secondary', {parts = {{field=3, type='unsigned'}}}) + --- + - unique: true + parts: + - type: unsigned + is_nullable: false + fieldno: 3 + id: 2 + space_id: 512 + type: TREE + name: secondary + ... + tarantool> box.space.tester.index.secondary:select({1993}) + --- + - - [3, 'Ace of Base', 1993] + ... + +.. _partial_key_search: + +3. The search may be for some key parts starting with the prefix of + the key. Notice that partial key searches are available only in TREE indexes. + +.. code-block:: tarantoolsession + + -- Create an index with three parts + tarantool> box.space.tester:create_index('tertiary', {parts = {{field = 2, type = 'string'}, {field=3, type='unsigned'}, {field=4, type='unsigned'}}}) + --- + - unique: true + parts: + - type: string + is_nullable: false + fieldno: 2 + - type: unsigned + is_nullable: false + fieldno: 3 + - type: unsigned + is_nullable: true + fieldno: 4 + id: 6 + space_id: 513 + type: TREE + name: tertiary + ... + -- Make a partial search + tarantool> box.space.tester.index.tertiary:select({'Scorpions', 2015}) + --- + - - [2, 'Scorpions', 2015, 4] + ... + +4. The search may be for all fields, using a table for the value: + +.. code-block:: tarantoolsession + + tarantool> box.space.tester.index.tertiary:select({'Roxette', 2016, 3}) + --- + - - [4, 'Roxette', 2016, 3] + ... + +or the search can be for one field, using a table or a scalar: + +.. code-block:: tarantoolsession - Space definitions and index definitions are stored permanently in Tarantool's - system spaces :ref:`_space ` and :ref:`_index ` - (for details, see reference on :ref:`box.space ` submodule). + tarantool> box.space.tester.index.tertiary:select({'Roxette'}) + --- + - - [1, 'Roxette', 1986, 5] + - [4, 'Roxette', 2016, 3] + ... - You can add, drop, or alter the definitions at runtime, with some restrictions. - See syntax details in reference on :ref:`box ` module. +.. admonition:: Tip + :class: fact -Read more about index operations :ref:`here `. + You can add, drop, or alter the definitions at runtime, with some restrictions. + Read more in section :ref:`index operations ` + and in reference for :doc:`box.index submodule `. \ No newline at end of file diff --git a/doc/reference/reference_lua/box_index/select.rst b/doc/reference/reference_lua/box_index/select.rst index d330af9fa9..b63aa206c7 100644 --- a/doc/reference/reference_lua/box_index/select.rst +++ b/doc/reference/reference_lua/box_index/select.rst @@ -93,53 +93,3 @@ index_object:select() tuple in the tuple set that would be returned by ``select``. However, if there is more than one tuple in the tuple set, then ``get`` throws an error. - - - **Example with BITSET index:** - - The following script shows creation and search with a BITSET index. - Notice: BITSET cannot be unique, so first a primary-key index is created. - Notice: bit values are entered as hexadecimal literals for easier reading. - - .. code-block:: tarantoolsession - - tarantool> s = box.schema.space.create('space_with_bitset') - tarantool> s:create_index('primary_index', { - > parts = {1, 'string'}, - > unique = true, - > type = 'TREE' - > }) - tarantool> s:create_index('bitset_index', { - > parts = {2, 'unsigned'}, - > unique = false, - > type = 'BITSET' - > }) - tarantool> s:insert{'Tuple with bit value = 01', 0x01} - tarantool> s:insert{'Tuple with bit value = 10', 0x02} - tarantool> s:insert{'Tuple with bit value = 11', 0x03} - tarantool> s.index.bitset_index:select(0x02, { - > iterator = box.index.EQ - > }) - --- - - - ['Tuple with bit value = 10', 2] - ... - tarantool> s.index.bitset_index:select(0x02, { - > iterator = box.index.BITS_ANY_SET - > }) - --- - - - ['Tuple with bit value = 10', 2] - - ['Tuple with bit value = 11', 3] - ... - tarantool> s.index.bitset_index:select(0x02, { - > iterator = box.index.BITS_ALL_SET - > }) - --- - - - ['Tuple with bit value = 10', 2] - - ['Tuple with bit value = 11', 3] - ... - tarantool> s.index.bitset_index:select(0x02, { - > iterator = box.index.BITS_ALL_NOT_SET - > }) - --- - - - ['Tuple with bit value = 01', 1] - ... diff --git a/doc/reference/reference_lua/box_space/create_index.rst b/doc/reference/reference_lua/box_space/create_index.rst index 208ee2ff81..19dc13405a 100644 --- a/doc/reference/reference_lua/box_space/create_index.rst +++ b/doc/reference/reference_lua/box_space/create_index.rst @@ -8,10 +8,10 @@ On this page: * :ref:`create_index() description ` * :ref:`Details about index field types ` * :ref:`Allowing null for an indexed key ` -* :ref:`Using field names instead of field numbers ` -* :ref:`Using the path option for map fields (JSON-indexes) ` -* :ref:`Using the path option with [*] ` -* :ref:`Making a functional index with space_object:create_index() ` +* :ref:`Creating an index using field names instead of field numbers ` +* :ref:`Creating an index using the path option for map fields (JSON-path indexes) ` +* :ref:`Creating an index using the path option with [*] ` +* :ref:`Creating a functional index with space_object:create_index() ` .. class:: space_object @@ -328,7 +328,7 @@ Nulls may appear multiple times even in a unique index. Example: .. _box_space-field_names: -------------------------------------------------------------------------------- -Using field names instead of field numbers +Creating an index using field names instead of field numbers -------------------------------------------------------------------------------- ``create_index()`` can use @@ -357,7 +357,7 @@ The variations include omitting the type, using numbers, and adding extra braces .. _box_space-path: -------------------------------------------------------------------------------- -Using the path option for map fields (JSON-indexes) +Creating an index using the path option for map fields (JSON-path indexes) -------------------------------------------------------------------------------- To create an index for a field that is a map (a path string and a scalar value), @@ -394,7 +394,7 @@ secondary indexes must be created before tuples are inserted. .. _box_space-path_multikey: -------------------------------------------------------------------------------- -Using the path option with [*] +Creating a multikey index using the path option with [*] -------------------------------------------------------------------------------- The string in a path option can contain '[*]' which is called @@ -450,7 +450,7 @@ Some restrictions exist: .. _box_space-index_func: -------------------------------------------------------------------------------- -Making a functional index with space_object:create_index() +Creating a functional index -------------------------------------------------------------------------------- Functional indexes are indexes that call a user-defined function for forming From 721f08b896be457fe735a329976c1f9ec6cc009f Mon Sep 17 00:00:00 2001 From: Natalia Ogoreltseva Date: Fri, 19 Feb 2021 18:26:21 +0300 Subject: [PATCH 2/7] update table about indexes features --- doc/book/box/indexes.rst | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/doc/book/box/indexes.rst b/doc/book/box/indexes.rst index 6438ea6b18..ee2102d2e3 100644 --- a/doc/book/box/indexes.rst +++ b/doc/book/box/indexes.rst @@ -126,13 +126,7 @@ We give an overview of index features in the following table: - \- - \- - * - updates - - \+ - - \+ - - \- - - \- - - * - deletes + * - can be primary key - \+ - \+ - \- From 0f726532766693ff44bb6898bedc00221bc59195 Mon Sep 17 00:00:00 2001 From: Natalia Ogoreltseva <37013254+Onvember@users.noreply.github.com> Date: Wed, 24 Feb 2021 13:33:22 +0300 Subject: [PATCH 3/7] Apply suggestions from code review Co-authored-by: Nick Volynkin --- doc/book/box/indexes.rst | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/doc/book/box/indexes.rst b/doc/book/box/indexes.rst index ee2102d2e3..13a7d0623a 100644 --- a/doc/book/box/indexes.rst +++ b/doc/book/box/indexes.rst @@ -3,7 +3,7 @@ Indexes ================================================================================ -An **index** is special data structure that stores a group of key values and +An **index** is a special data structure that stores a group of key values and pointers. It is used for efficient manipulations with data. As with spaces, you should specify the index **name**, and let Tarantool @@ -36,7 +36,7 @@ An index definition may include identifiers of tuple fields and their expected A recommended design pattern for a data model is to base primary keys on the first fields of a tuple, because this speeds up tuple comparison. -Let's look on an example where we first define the primary index (named 'primary') +Let's look at an example where we first define the primary index (named 'primary') based on field #1 of each tuple: .. code-block:: tarantoolsession @@ -177,17 +177,17 @@ Use HASH index: * if it is a secondary key * if you 100% won't need to make it non-unique * if you really need that 2-5% performance improvement -* if you have taken measurements on your data and you see this increase in performance +* if you have taken measurements on your data and you see an increase in performance * if you save every byte on tuples (HASH is a little more compact) ******************************************************************************** RTREE indexes ******************************************************************************** -RTREE is a multidimensional index supporting up to 32 number of dimensions. -It is used especially for indexing spacial information, such as geographical +RTREE is a multidimensional index supporting up to 32 dimensions. +It is used especially for indexing spatial information, such as geographical objects. In :ref:`this example ` -we demonstrate spacial searches via RTREE index. +we demonstrate spatial searches via RTREE index. RTREE index can accept two types of ``distance`` functions: ``euclid`` and ``manhattan``. @@ -219,11 +219,11 @@ BITSET indexes ******************************************************************************** Bitset is a bit mask. You should use it when you need to search by bit masks. -This can be, for example, storing a vector of attributes and search by these attributes. +This can be, for example, storing a vector of attributes and searching by these attributes. **Example 1:** -The following script shows creation and search with a BITSET index. +The following script shows creating and searching with a BITSET index. Notice that BITSET cannot be unique, so first a primary-key index is created, and bit values are entered as hexadecimal literals for easier reading. @@ -298,8 +298,9 @@ Additionally, there exist :doc:`index iterator operations `. They can only be used with code in Lua and C/C++. Index iterators are for traversing indexes one key at a time, taking advantage of features that are -specific to an index type, for example evaluating Boolean expressions when -traversing BITSET indexes, or going in descending order when traversing TREE indexes. +specific to an index type. +For example, they can be used for evaluating Boolean expressions when +traversing BITSET indexes, or for going in descending order when traversing TREE indexes. .. _index-box_index-operations: @@ -312,8 +313,8 @@ then it also changes the index keys defined for the tuple. The simple index-creation operation that we've illustrated before is: -.. cssclass:: highlight -.. parsed-literal:: +.. cssclass:: highlight +.. parsed-literal:: :samp:`box.space.{space-name}:create_index('{index-name}')` @@ -322,14 +323,14 @@ This creates a unique TREE index on the first field of all tuples The simple SELECT request that we've illustrated before is: -.. cssclass:: highlight -.. parsed-literal:: +.. cssclass:: highlight +.. parsed-literal:: :extsamp:`box.space.{*{space-name}*}:select({*{value}*})` This looks for a single tuple via the first index. Since the first index is always unique, the maximum number of returned tuples will be: one. -You can call ``select()`` without arguments, causing all tuples to be returned. +You can call ``select()`` without arguments, and it will return all tuples. Let's continue working with the space 'tester' created in the :ref:`"Getting started" exercises ` but first modify it: @@ -383,7 +384,7 @@ And insert another tuple: The :ref:`comparison operators ` are LT, LE, EQ, REQ, GE, GT (for "less than", "less than or equal", "equal", "reversed equal", "greater than or equal", "greater than" respectively). -Comparisons make sense if and only if the index type is ‘TREE'. +Comparisons make sense if and only if the index type is 'TREE'. This type of search may return more than one tuple; if so, the tuples will be in descending order by key when the comparison operator is LT or LE or REQ, @@ -469,4 +470,4 @@ or the search can be for one field, using a table or a scalar: You can add, drop, or alter the definitions at runtime, with some restrictions. Read more in section :ref:`index operations ` - and in reference for :doc:`box.index submodule `. \ No newline at end of file + and in reference for :doc:`box.index submodule `. From 78bc89aa2e9738d3d97544498451b5816d91feb0 Mon Sep 17 00:00:00 2001 From: Natalia Ogoreltseva Date: Wed, 24 Feb 2021 14:29:39 +0300 Subject: [PATCH 4/7] fix indentation for list --- doc/book/box/indexes.rst | 194 +++++++++++++++++++-------------------- 1 file changed, 97 insertions(+), 97 deletions(-) diff --git a/doc/book/box/indexes.rst b/doc/book/box/indexes.rst index 13a7d0623a..009dda8f3b 100644 --- a/doc/book/box/indexes.rst +++ b/doc/book/box/indexes.rst @@ -335,7 +335,7 @@ You can call ``select()`` without arguments, and it will return all tuples. Let's continue working with the space 'tester' created in the :ref:`"Getting started" exercises ` but first modify it: -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession tarantool> box.space.tester:format({ > {name = 'id', type = 'unsigned'}, @@ -347,7 +347,7 @@ started" exercises ` but first modify it: Add the rate to the tuple #1 and #2: -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession tarantool> box.space.tester:update(1, {{'=', 4, 5}}) --- @@ -361,7 +361,7 @@ Add the rate to the tuple #1 and #2: And insert another tuple: -.. code-block:: tarantoolsession +.. code-block:: tarantoolsession tarantool> box.space.tester:insert({4, 'Roxette', 2016, 3}) --- @@ -370,100 +370,100 @@ And insert another tuple: **The existing SELECT variations:** -1. The search can use comparisons other than equality. - -.. code-block:: tarantoolsession - - tarantool> box.space.tester:select(1, {iterator = 'GT'}) - --- - - - [2, 'Scorpions', 2015, 4] - - [3, 'Ace of Base', 1993] - - [4, 'Roxette', 2016, 3] - ... - -The :ref:`comparison operators ` are LT, LE, EQ, REQ, GE, GT -(for "less than", "less than or equal", "equal", "reversed equal", -"greater than or equal", "greater than" respectively). -Comparisons make sense if and only if the index type is 'TREE'. - -This type of search may return more than one tuple; if so, the tuples will be -in descending order by key when the comparison operator is LT or LE or REQ, -otherwise in ascending order. - -2. The search can use a secondary index. - -For a primary-key search, it is optional to specify an index name. -For a secondary-key search, it is mandatory. - -.. code-block:: tarantoolsession - - tarantool> box.space.tester:create_index('secondary', {parts = {{field=3, type='unsigned'}}}) - --- - - unique: true - parts: - - type: unsigned - is_nullable: false - fieldno: 3 - id: 2 - space_id: 512 - type: TREE - name: secondary - ... - tarantool> box.space.tester.index.secondary:select({1993}) - --- - - - [3, 'Ace of Base', 1993] - ... - -.. _partial_key_search: - -3. The search may be for some key parts starting with the prefix of - the key. Notice that partial key searches are available only in TREE indexes. - -.. code-block:: tarantoolsession - - -- Create an index with three parts - tarantool> box.space.tester:create_index('tertiary', {parts = {{field = 2, type = 'string'}, {field=3, type='unsigned'}, {field=4, type='unsigned'}}}) - --- - - unique: true - parts: - - type: string - is_nullable: false - fieldno: 2 - - type: unsigned - is_nullable: false - fieldno: 3 - - type: unsigned - is_nullable: true - fieldno: 4 - id: 6 - space_id: 513 - type: TREE - name: tertiary - ... - -- Make a partial search - tarantool> box.space.tester.index.tertiary:select({'Scorpions', 2015}) - --- - - - [2, 'Scorpions', 2015, 4] - ... - -4. The search may be for all fields, using a table for the value: - -.. code-block:: tarantoolsession - - tarantool> box.space.tester.index.tertiary:select({'Roxette', 2016, 3}) - --- - - - [4, 'Roxette', 2016, 3] - ... - -or the search can be for one field, using a table or a scalar: - -.. code-block:: tarantoolsession - - tarantool> box.space.tester.index.tertiary:select({'Roxette'}) - --- - - - [1, 'Roxette', 1986, 5] - - [4, 'Roxette', 2016, 3] - ... +1. The search can use comparisons other than equality. + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:select(1, {iterator = 'GT'}) + --- + - - [2, 'Scorpions', 2015, 4] + - [3, 'Ace of Base', 1993] + - [4, 'Roxette', 2016, 3] + ... + + The :ref:`comparison operators ` are LT, LE, EQ, REQ, GE, GT + (for "less than", "less than or equal", "equal", "reversed equal", + "greater than or equal", "greater than" respectively). + Comparisons make sense if and only if the index type is 'TREE'. + + This type of search may return more than one tuple; if so, the tuples will be + in descending order by key when the comparison operator is LT or LE or REQ, + otherwise in ascending order. + +2. The search can use a secondary index. + + For a primary-key search, it is optional to specify an index name. + For a secondary-key search, it is mandatory. + + .. code-block:: tarantoolsession + + tarantool> box.space.tester:create_index('secondary', {parts = {{field=3, type='unsigned'}}}) + --- + - unique: true + parts: + - type: unsigned + is_nullable: false + fieldno: 3 + id: 2 + space_id: 512 + type: TREE + name: secondary + ... + tarantool> box.space.tester.index.secondary:select({1993}) + --- + - - [3, 'Ace of Base', 1993] + ... + + .. _partial_key_search: + +3. The search may be for some key parts starting with the prefix of + the key. Notice that partial key searches are available only in TREE indexes. + + .. code-block:: tarantoolsession + + -- Create an index with three parts + tarantool> box.space.tester:create_index('tertiary', {parts = {{field = 2, type = 'string'}, {field=3, type='unsigned'}, {field=4, type='unsigned'}}}) + --- + - unique: true + parts: + - type: string + is_nullable: false + fieldno: 2 + - type: unsigned + is_nullable: false + fieldno: 3 + - type: unsigned + is_nullable: true + fieldno: 4 + id: 6 + space_id: 513 + type: TREE + name: tertiary + ... + -- Make a partial search + tarantool> box.space.tester.index.tertiary:select({'Scorpions', 2015}) + --- + - - [2, 'Scorpions', 2015, 4] + ... + +4. The search may be for all fields, using a table for the value: + + .. code-block:: tarantoolsession + + tarantool> box.space.tester.index.tertiary:select({'Roxette', 2016, 3}) + --- + - - [4, 'Roxette', 2016, 3] + ... + + or the search can be for one field, using a table or a scalar: + + .. code-block:: tarantoolsession + + tarantool> box.space.tester.index.tertiary:select({'Roxette'}) + --- + - - [1, 'Roxette', 1986, 5] + - [4, 'Roxette', 2016, 3] + ... .. admonition:: Tip :class: fact From f3eb679ad98d30267d31f9e690759437e387296b Mon Sep 17 00:00:00 2001 From: Natalia Ogoreltseva Date: Wed, 24 Feb 2021 15:38:58 +0300 Subject: [PATCH 5/7] add more info about RTREE indexes from Tarantool wiki --- doc/book/box/indexes.rst | 192 +++++++++++++++++++++++++++++++++++---- 1 file changed, 176 insertions(+), 16 deletions(-) diff --git a/doc/book/box/indexes.rst b/doc/book/box/indexes.rst index 009dda8f3b..47d648da6c 100644 --- a/doc/book/box/indexes.rst +++ b/doc/book/box/indexes.rst @@ -184,35 +184,195 @@ Use HASH index: RTREE indexes ******************************************************************************** -RTREE is a multidimensional index supporting up to 32 dimensions. +RTREE is a multidimensional index supporting up to 20 dimensions. It is used especially for indexing spatial information, such as geographical -objects. In :ref:`this example ` -we demonstrate spatial searches via RTREE index. +objects. In :ref:`this example ` we demonstrate spatial searches +via RTREE index. -RTREE index can accept two types of ``distance`` functions: -``euclid`` and ``manhattan``. +RTREE index could not be primary, and could not be unique. +The option list of this type of index may contain ``dimension`` and ``distance`` options. +The ``parts`` definition must contain the one and only part with type ``array``. +RTREE index can accept two types of ``distance`` functions: ``euclid`` and ``manhattan``. -**Example:** +**Example 1:** + +.. code-block:: lua + + s = box.schema.create_space("test") + i = s:create_index('primary', { type = 'HASH', parts = {1, 'num'} }) + r = s:create_index('spatial', { type = 'RTREE', unique = false, parts = {2, 'array'} }) + +Corresponding tuple field thus must be an array of 2 or 4 numbers. +2 numbers mean a point {x, y}; +4 numbers mean a rectangle {x1, y1, x2, y2}, +where (x1, y1) and (x2, y2) - diagonal point of the rectangle. + +.. code-block:: lua + + s:insert{1, {1, 1}} + s:insert{2, {2, 2, 3, 3}} + +Selection results depend on a chosen iterator. +The default EQ iterator searches for an exact rectangle, +a point is treated as zero width and height rectangle: .. code-block:: tarantoolsession - tarantool> box.schema.space.create('rtree_example') - tarantool> box.space.rtree_example:create_index('primary') - tarantool> box.space.rtree_example:create_index('rtree',{unique=false,type='RTREE', parts={2,'ARRAY'}}) - tarantool> box.space.rtree_example:insert{1, {3, 5, 9, 10}} - tarantool> box.space.rtree_example:insert{2, {10, 11}} - tarantool> box.space.rtree_example.index.rtree:select({4, 7, 5, 9}, {iterator = 'GT'}) + tarantool> r:select{1, 1} + --- + - - [1, [1, 1]] + ... -The result will be: + tarantool> r:select{1, 1, 1, 1} + --- + - - [1, [1, 1]] + ... + + tarantool> r:select{2, 2} + --- + - [] + ... + + tarantool> r:select{2, 2, 3, 3} + --- + - - [2, [2, 2, 3, 3]] + ... + +Iterator ALL, which is the default when no key is specified, +selects all tuples in arbitrary order: .. code-block:: tarantoolsession + tarantool> r:select{} --- - - - [1, [3, 5, 9, 10]] + - - [1, [1, 1]] + - [2, [2, 2, 3, 3]] ... -because a rectangle whose corners are at coordinates ``4,7,5,9`` is entirely -within a rectangle whose corners are at coordinates ``3,5,9,10``. +Iterator LE (less or equal) searches for tuples with their rectangles +within a specified rectangle: + +.. code-block:: tarantoolsession + + tarantool> r:select({1, 1, 2, 2}, {iterator='le'}) + --- + - - [1, [1, 1]] + ... + +Iterator LT (less than, or strictly less) searches for tuples +with their rectangles strictly within a specified rectangle: + +.. code-block:: tarantoolsession + + tarantool> r:select({0, 0, 3, 3}, {iterator='lt'}) + --- + - - [1, [1, 1]] + ... + +Iterator GE searches for tuples with a specified rectangle within their rectangles: + +.. code-block:: tarantoolsession + + tarantool> r:select({1, 1}, {iterator='ge'}) + --- + - - [1, [1, 1]] + ... + +Iterator GT searches for tuples with a specified rectangle strictly within their rectangles: + +.. code-block:: tarantoolsession + + tarantool> r:select({2.1, 2.1, 2.9, 2.9}, {itearator='gt'}) + --- + - [] + ... +Iterator OVERLAPS searches for tuples with their rectangles overlapping specified rectangle: + +.. code-block:: tarantoolsession + + tarantool> r:select({0, 0, 10, 2}, {iterator='overlaps'}) + --- + - - [1, [1, 1]] + - [2, [2, 2, 3, 3]] + ... + +Iterator NEIGHBOR searches for all tuples and orders them by distance to the specified point: + +.. code-block:: tarantoolsession + + tarantool> for i=1,10 do + > for j=1,10 do + > s:insert{i*10+j, {i, j, i+1, j+1}} + > end + > end + --- + ... + + tarantool> r:select({1, 1}, {iterator='neighbor', limit=5}) + --- + - - [11, [1, 1, 2, 2]] + - [12, [1, 2, 2, 3]] + - [21, [2, 1, 3, 2]] + - [22, [2, 2, 3, 3]] + - [31, [3, 1, 4, 2]] + ... + +**Example 2:** + +3D, 4D and more dimensional RTREE indexes work in the same way as 2D except +that user must specify more coordinates in requests. +Here's short example of using 4D tree: + +.. code-block:: tarantoolsession + + tarantool> s = box.schema.create_space('test') + --- + ... + + tarantool> i = s:create_index('primary', { type = 'HASH', parts = {1, 'num'} }) + --- + ... + + tarantool> r = s:create_index('spatial', { type = 'RTREE', unique = false, dimension = 4, parts = {2, 'array'} }) + --- + ... + + tarantool> s:insert{1, {1, 2, 3, 4}} -- insert 4D point + --- + - [1, [1, 2, 3, 4]] + ... + + tarantool> s:insert{2, {1, 1, 1, 1, 2, 2, 2, 2}} -- insert 4D box + --- + - [2, [1, 1, 1, 1, 2, 2, 2, 2]] + ... + + tarantool> r:select{1, 2, 3, 4} -- find exact point + --- + - - [1, [1, 2, 3, 4]] + ... + + tarantool> r:select({0, 0, 0, 0, 3, 3, 3, 3}, {iterator = 'LE'}) -- select from 4D box + --- + - - [2, [1, 1, 1, 1, 2, 2, 2, 2]] + ... + + tarantool> r:select({0, 0, 0, 0}, {iterator = 'neighbor'}) -- select neighbours + --- + - - [2, [1, 1, 1, 1, 2, 2, 2, 2]] + - [1, [1, 2, 3, 4]] + ... + +.. NOTE:: + + Don't forget that select NEIGHBOR iterator without limit + extract entire space in order of increasing distance and + that could be tons of data with corresponding performance. + + And another frequent mistake is to specify iterator type without quotes, + in such way: ``r:select(rect, {iterator = LE})``. + This leads to silent EQ select, because ``LE`` is undefined variable and + treated as nil, so iterator is unset and default used. ******************************************************************************** BITSET indexes From 8acf1f898359355536a5fffe94693da3a925f446 Mon Sep 17 00:00:00 2001 From: Natalia Ogoreltseva Date: Wed, 24 Feb 2021 15:39:58 +0300 Subject: [PATCH 6/7] small improvements after review --- doc/book/box/data_model.rst | 2 +- doc/book/box/indexes.rst | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/doc/book/box/data_model.rst b/doc/book/box/data_model.rst index 30b0d5c800..58459d6ffb 100644 --- a/doc/book/box/data_model.rst +++ b/doc/book/box/data_model.rst @@ -385,7 +385,7 @@ Full information is in section | ``'string'`` | :ref:`string ` | TREE, BITSET or HASH | | (may also be called ``‘str’``) | | | +--------------------------------+-------------------------------------------+--------------------------------------+ - | ``'varbinary'`` | :ref:`varbinary ` | TREE or HASH | + | ``'varbinary'`` | :ref:`varbinary ` | TREE, BITSET or HASH | +--------------------------------+-------------------------------------------+--------------------------------------+ | ``'uuid'`` | :ref:`uuid ` | TREE or HASH | +--------------------------------+-------------------------------------------+--------------------------------------+ diff --git a/doc/book/box/indexes.rst b/doc/book/box/indexes.rst index 47d648da6c..fc8fc5f90b 100644 --- a/doc/book/box/indexes.rst +++ b/doc/book/box/indexes.rst @@ -4,7 +4,8 @@ Indexes ================================================================================ An **index** is a special data structure that stores a group of key values and -pointers. It is used for efficient manipulations with data. +pointers. It is used for efficient manipulations with data +and should be chosen depending on the task. As with spaces, you should specify the index **name**, and let Tarantool come up with a unique **numeric identifier** ("index id"). @@ -90,13 +91,13 @@ We give an overview of index features in the following table: - RTREE - BITSET - * - unique + * - ``unique`` - \+ - \+ - \- - \- - * - non-unique + * - ``non-unique`` - \+ - \- - \+ @@ -108,7 +109,7 @@ We give an overview of index features in the following table: - \- - \- - * - multi-part + * - can be multi-part - \+ - \+ - \- @@ -132,7 +133,7 @@ We give an overview of index features in the following table: - \- - \- - * - exclude_null (version 2.8+) + * - ``exclude_null`` (version 2.8+) - \+ - \- - \- From 01f1670bb4bb190b7a008de90315b6304d615e9c Mon Sep 17 00:00:00 2001 From: Natalia Ogoreltseva Date: Wed, 24 Feb 2021 15:58:26 +0300 Subject: [PATCH 7/7] add links to reference --- doc/book/box/data_model.rst | 5 +++-- doc/book/box/indexes.rst | 34 ++++++++++++++++++++++++---------- 2 files changed, 27 insertions(+), 12 deletions(-) diff --git a/doc/book/box/data_model.rst b/doc/book/box/data_model.rst index 58459d6ffb..cd35303a2c 100644 --- a/doc/book/box/data_model.rst +++ b/doc/book/box/data_model.rst @@ -74,10 +74,11 @@ An **index** is a group of key values and pointers. As with spaces, you should specify the index **name**, and let Tarantool come up with a unique **numeric identifier** ("index id"). -An index always has a **type**. The default index type is 'TREE'. +An index always has a **type**. The default index type is :ref:`TREE `. TREE indexes are provided by all Tarantool engines, can index unique and non-unique values, support partial key searches, comparisons and ordered results. -Additionally, memtx engine supports HASH, RTREE and BITSET indexes. +Additionally, memtx engine supports :ref:`HASH `, +:ref:`RTREE ` and :ref:`BITSET ` indexes. An index may be **multi-part**, that is, you can declare that an index key value is composed of two or more fields in the tuple, in any order. diff --git a/doc/book/box/indexes.rst b/doc/book/box/indexes.rst index fc8fc5f90b..2e6620f411 100644 --- a/doc/book/box/indexes.rst +++ b/doc/book/box/indexes.rst @@ -145,6 +145,8 @@ We give an overview of index features in the following table: - ALL, EQ, GT, GE, LT, LE, OVERLAPS, NEIGHBOR - ALL, EQ, BITS_ALL_SET, BITS_ANY_SET, BITS_ALL_NOT_SET +.. _indexes-tree: + ******************************************************************************** TREE indexes ******************************************************************************** @@ -157,6 +159,8 @@ This is a universal type of indexes, for most cases it will be the best choice. Additionally, memtx engine supports HASH, RTREE and BITSET indexes. +.. _indexes-hash: + ******************************************************************************** HASH indexes ******************************************************************************** @@ -181,6 +185,8 @@ Use HASH index: * if you have taken measurements on your data and you see an increase in performance * if you save every byte on tuples (HASH is a little more compact) +.. _indexes-rtree: + ******************************************************************************** RTREE indexes ******************************************************************************** @@ -287,6 +293,7 @@ Iterator GT searches for tuples with a specified rectangle strictly within their --- - [] ... + Iterator OVERLAPS searches for tuples with their rectangles overlapping specified rectangle: .. code-block:: tarantoolsession @@ -375,12 +382,15 @@ Here's short example of using 4D tree: This leads to silent EQ select, because ``LE`` is undefined variable and treated as nil, so iterator is unset and default used. +.. _indexes-bitset: + ******************************************************************************** BITSET indexes ******************************************************************************** Bitset is a bit mask. You should use it when you need to search by bit masks. -This can be, for example, storing a vector of attributes and searching by these attributes. +This can be, for example, storing a vector of attributes and searching by these +attributes. **Example 1:** @@ -461,7 +471,8 @@ They can only be used with code in Lua and C/C++. Index iterators are for traversing indexes one key at a time, taking advantage of features that are specific to an index type. For example, they can be used for evaluating Boolean expressions when -traversing BITSET indexes, or for going in descending order when traversing TREE indexes. +traversing BITSET indexes, or for going in descending order when traversing TREE +indexes. .. _index-box_index-operations: @@ -472,7 +483,8 @@ Index operations Index operations are automatic: if a data-manipulation request changes a tuple, then it also changes the index keys defined for the tuple. -The simple index-creation operation that we've illustrated before is: +The simple :doc:`index-creation ` +operation that we've illustrated before is: .. cssclass:: highlight .. parsed-literal:: @@ -482,7 +494,8 @@ The simple index-creation operation that we've illustrated before is: This creates a unique TREE index on the first field of all tuples (often called "Field#1"), which is assumed to be numeric. -The simple SELECT request that we've illustrated before is: +The simple :doc:`SELECT ` request +that we've illustrated before is: .. cssclass:: highlight .. parsed-literal:: @@ -490,11 +503,12 @@ The simple SELECT request that we've illustrated before is: :extsamp:`box.space.{*{space-name}*}:select({*{value}*})` This looks for a single tuple via the first index. Since the first index -is always unique, the maximum number of returned tuples will be: one. +is always unique, the maximum number of returned tuples will be 1. You can call ``select()`` without arguments, and it will return all tuples. Let's continue working with the space 'tester' created in the :ref:`"Getting -started" exercises ` but first modify it: +started" exercises ` but first modify it via +:doc:`format() `: .. code-block:: tarantoolsession @@ -506,7 +520,8 @@ started" exercises ` but first modify it: --- ... -Add the rate to the tuple #1 and #2: +Add the rate to the tuple #1 and #2 via +:doc:`update function `: .. code-block:: tarantoolsession @@ -519,8 +534,7 @@ Add the rate to the tuple #1 and #2: - [2, 'Scorpions', 2015, 4] ... - -And insert another tuple: +And :doc:`insert ` another tuple: .. code-block:: tarantoolsession @@ -545,7 +559,7 @@ And insert another tuple: The :ref:`comparison operators ` are LT, LE, EQ, REQ, GE, GT (for "less than", "less than or equal", "equal", "reversed equal", "greater than or equal", "greater than" respectively). - Comparisons make sense if and only if the index type is 'TREE'. + Comparisons make sense if and only if the index type is TREE. This type of search may return more than one tuple; if so, the tuples will be in descending order by key when the comparison operator is LT or LE or REQ,