我有一个 PostgreSQL 数据库,在使用索引和分区时我注意到一个奇怪的行为。引擎版本为10.21。
现在,我有一个具有以下结构的表:
guid varchar(50) PK
guid_a varchar(50)
data text
part_key varchar(2)
还有其他列,但它们无关紧要。我必须在此表上运行的查询如下所示'
select * from mytable where guid_a = 'jxxxxx-xxxxxxx' and data like '%7263628%';
让我解释一下:guid_a 列包含一个以以下格式标识人员的代码:“jxxxx-xxxxxxx”,其中“x”是数字。前两位数字从 00 到 99,因此,例如:
j01xxx-xxxxxx
j02xxx-xxxxxx
...
j99xxx-xxxxxx
我在此列上创建了一个索引,然后还在数据列上使用 trgm 模块创建了一个索引。启动查询后,我的性能得到了巨大的提高。到目前为止一切都很好。
我还决定使用分区(该表有640 万条记录)并且我在part_key列上创建了99个分区(按列表),该列仅包含guid_a值的前两位数字。我获得了 99 个分区,每个分区平均有 65000 行。每个分区都有我之前谈到的相同索引。性能再次提升。显然le查询对part_key还有另一个条件,以便引擎知道应该查询哪个分区。
现在奇怪的事情。我删除了没有分区的表上的 trgm 索引,令人惊讶的是:它更快。甚至比分区表还要快。甚至删除分区表上的 trgm 索引。
我在解释中注意到的是,对非分区表的查询强制引擎仅进行索引扫描(然后不应该对数据表上的第二个条件进行另一次扫描吗?)。
另一方面,在分区表上,它会进行 hitman 索引扫描,然后进行堆扫描,然后进行追加。这显然比索引所有 640 万行的成本还要高。
我用不同的值进行了不同的测试,但结果相同。
表现:
一般:
在分区表上为 11 毫秒 在仅在 guid_a 上具有一个索引的非分区表上为 9 毫秒 在具有两个索引的非分区表上为 20 毫秒,第二个索引在使用 trgm 的数据列上。
这里发生了什么?