如何在Tarantool中通过SQL利用大小写不敏感索引查询列?
Tarantool: 实现SQL大小写不敏感查询并利用已创建的索引
首先,先回顾下你已经掌握的Lua API实现方式——通过给字符串索引指定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"}
用Lua API查询时确实能得到预期结果:
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\" where upper(\"col1\") = 'AAA'") --- - metadata: - name: id type: number - name: col1 type: string rows: - [1, 'aaa'] ...
正确的SQL写法
其实只需要在查询条件里显式指定collate "unicode_ci"就能解决问题:
tarantool> box.execute("select * from \"test\" where \"col1\" = 'AAA' collate \"unicode_ci\"") --- - metadata: - name: id type: number - name: col1 type: string rows: - [1, 'aaa'] ...
关键疑问:这个写法会利用已创建的索引吗?
答案是肯定的。Tarantool会自动匹配与查询中指定的排序规则(unicode_ci)一致的索引,也就是你之前创建的col1_idx。如果不确定,可以用EXPLAIN语句查看查询计划:
tarantool> box.execute("EXPLAIN select * from \"test\" where \"col1\" = 'AAA' collate \"unicode_ci\"") --- - operations: - index_access: index: col1_idx key: ['AAA'] space: test type: eq ...
从执行计划里能清晰看到,查询确实走了col1_idx索引的等值查询,而不是全表扫描。当然,如果没有提前创建这个索引,SQL语句虽然也能执行,但会退化为全表扫描,性能会大打折扣,所以提前建好对应排序规则的索引非常关键。
内容的提问来源于stack exchange,提问作者Mike Siomkin
相关产品推荐
相关产品推荐

