PostgreSQL citext索引与较低的表达式索引性能

问题描述 投票:2回答:1

我想决定使用带有索引的citext列还是使用带有text索引的lower()列。

我做了一些基准测试。令我惊讶的是,使用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

但是任何事情都没有改变,即使我在创建索引后运行analyze并在select.Index中使用count(*)仍然继续使用lower()上的索引。

postgresql query-performance database-indexes
1个回答
2
投票

您的测试具有误导性。这里有两个问题:

  1. 在创建索引ANALYZE之后,您没有运行lowertextind。 没有它,PostgreSQL不知道lower(a)是如何分布的,并且可能会产生错误的成本估算。
  2. 通过使用SELECT *,您无意中允许仅索引扫描用于第一个查询,但不能用于第二个查询。这是因为第一个索引包含所有表列,但第二个索引不包含。 由于第二个索引不包含a,因此必须从表中获取值,从而导致额外的工作。 您可以使用SELECT count(*) FROM ...获得更公平的基准。
© www.soinside.com 2019 - 2024. All rights reserved.