【发布时间】:2019-04-11 08:23:13
【问题描述】:
我想决定是使用带有索引的citext 列还是使用带有lower() 索引的text 列。
我执行了一些基准测试。令我惊讶的是,使用lower() 上的索引进行搜索会导致索引扫描,但在citext 的情况下,我会得到仅索引扫描。我期待lower() 上的索引也会导致仅索引扫描。
此外,citext 索引的总成本为 4.44,但lower() 索引的总成本为 8.44。
所以我首先想到的是citext 列索引优于text 列上的表达式索引。
CREATE TABLE test_citext(a citext NOT NULL);
INSERT INTO test_citext
SELECT cast(x as text)
FROM generate_series(1, 1000000) AS x;
VACUUM (FREEZE, ANALYZE) test_citext;
create index citextind on test_citext(a);
Select * from test_citext where a = 'test';
--Index Only Scan.Total cost 4.44
CREATE TABLE test_textlowerindex(a text NOT NULL);
INSERT INTO test_textlowerindex
SELECT cast(x as text)
FROM generate_series(1, 1000000) AS x;
VACUUM (FREEZE, ANALYZE) test_textlowerindex;
create index lowertextind on test_textlowerindex(lower(a));
Select * from test_textlowerindex where lower(a) = 'test';
--Index Scan.Total cost 8.44
我说的对吗?
Laurenz Albe 先生感谢您的回答。如您所说,我更改了上面的脚本。 结果:
CREATE TABLE test_citext(a citext NOT NULL);
INSERT INTO test_citext
SELECT cast(x as text)
FROM generate_series(1, 1000000) AS x;
create index citextind on test_citext(a);
VACUUM (FREEZE, ANALYZE) test_citext;
Select count(*) from test_citext where a = 'test';
--Index Only Scan 4.44 + 4.46
CREATE TABLE test_textlowerindex(a text NOT NULL);
INSERT INTO test_textlowerindex
SELECT cast(x as text)
FROM generate_series(1, 1000000) AS x;
create index lowertextind on test_textlowerindex(lower(a));
VACUUM (FREEZE, ANALYZE) test_textlowerindex;
Select count(*) from test_textlowerindex where lower(a) = 'test';
--Index Scan 8.44 + 8.46
但任何事情都没有改变即使我在创建索引并在 select.Index 中使用 count(*) 后运行分析。索引扫描仍然继续使用 lower() 上的索引。
【问题讨论】:
-
我认为原因通常是“索引不能转换回小写值,所以它需要查看表”,但 SELECT lower(a) 也不会使用 Index Only。
标签: postgresql query-performance database-indexes