Запрос столбцов без учета регистра по SQL в Tarantool - PullRequest
3 голосов
/ 19 июня 2020

Мы знаем, что строковые индексы Tarantool можно сделать нечувствительными к регистру, указав опцию сопоставления: collation = "unicode_ci". Например:

t = box.schema.create_space("test")
t:format({{name = "id", type = "number"}, {name = "col1", type = "string"}})
t:create_index('primary')
t:create_index("col1_idx", {parts = {{field = "col1", type = "string", collation = "unicode_ci"}}})
t:insert{1, "aaa"}
t:insert{2, "bbb"}
t:insert{3, "ccc"}

Теперь мы можем выполнить запрос без учета регистра:

tarantool> t.index.col1_idx:select("AAA")
---
- - [1, 'aaa']
...

Но как это сделать, используя SQL? Это не работает:

tarantool> box.execute("select * from \"test\" where \"col1\" = 'AAA'")
---
- metadata:
  - name: id
    type: number
  - name: col1
    type: string
  rows: []
...

То же самое:

tarantool> box.execute("select * from \"test\" indexed by \"col1_idx\" where \"col1\" = 'AAA'")
---
- metadata:
  - name: id
    type: number
  - name: col1
    type: string
  rows: []
...

Есть подвох с плохой производительностью (полное сканирование). Мы не хотим этого, не так ли?

tarantool> box.execute("select * from \"test\" indexed by \"col1_idx\" where upper(\"col1\") = 'AAA'")
---
- metadata:
  - name: id
    type: number
  - name: col1
    type: string
  rows:
  - [1, 'aaa']
...

Наконец, у нас есть еще один обходной путь:

tarantool> box.execute("select * from \"test\" where \"col1\" = 'AAA' collate \"unicode_ci\"")
---
- metadata:
  - name: id
    type: number
  - name: col1
    type: string
  rows:
  - [1, 'aaa']
...

Но вопрос - использует ли он индекс ? Без индекса тоже работает ...

1 Ответ

3 голосов
/ 22 июня 2020

Можно проверить план запроса, чтобы выяснить, используется ли конкретный индекс или нет. Чтобы получить план запроса, просто добавьте префикс EXPLAIN QUERY PLAN к исходному запросу. Например:

tarantool>  box.execute("explain query plan select * from \"test\" where \"col1\" = 'AAA' collate \"unicode_ci\"")
---
- metadata:
  - name: selectid
    type: integer
  - name: order
    type: integer
  - name: from
    type: integer
  - name: detail
    type: text
  rows:
  - [0, 0, 0, 'SEARCH TABLE test USING COVERING INDEX col1_idx (col1=?) (~1 row)']
...

Итак, ответ - «да», в этом случае используется индекс. Что касается другого примера:

box.execute("select * from \"test\" indexed by \"col1_idx\" where \"col1\" = 'AAA'")

К сожалению, сопоставление в этом сравнении двоичное, поскольку сопоставление индекса игнорируется. В SQL при сравнении учитываются только сопоставления столбцов. Это ограничение будет устранено, как только соответствующая проблема будет закрыта.

...