分区可以用于 Postgres 中的 LIKE 查询吗?

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

我有一个巨大的单词表,我正在上面运行 LIKE 查询:

create table words
(
  id   int,
  word varchar
)

它的工作时间很长。索引没有多大帮助,所以我尝试按

word
列对其进行分区:

create table words
(
  id   int,
  word varchar
) partition by RANGE (word);

CREATE TABLE words_1 PARTITION OF words
  FOR VALUES FROM ('a') TO ('n');

CREATE TABLE words_2 PARTITION OF words
  FOR VALUES FROM ('n') TO ('z');

注意:实际上我计划为每个字母创建 1 个分区。为了简单起见,仅使用其中 2 个。

因此,分区似乎可以与相等和 gt/lt 运算符一起使用:

explain
select * from words where word = 'abc'
Seq Scan on words_1 words  (cost=0.00..25.88 rows=6 width=36)
  Filter: ((word)::text = 'abc'::text)
explain
select * from words where word >= 'nth'
Seq Scan on words_2 words  (cost=0.00..25.88 rows=423 width=36)
  Filter: ((word)::text >= 'nth'::text)

但是在 LIKE 查询上,它会继续扫描两个分区:

explain
select * from words where word LIKE 'abc%'
Append  (cost=0.00..51.81 rows=12 width=36)
  ->  Seq Scan on words_1  (cost=0.00..25.88 rows=6 width=36)
        Filter: ((word)::text ~~ 'abc'::text)
  ->  Seq Scan on words_2  (cost=0.00..25.88 rows=6 width=36)
        Filter: ((word)::text ~~ 'abc'::text)

有没有办法让分区对 LIKE 查询起作用?

也许还有其他方法可以实现我想要的吗?

postgresql sql-like partitioning
2个回答
1
投票

我无法复制你的结果。您的查询使用索引,即使只有少数行。确保您的表已被分析并使用

explain analyze
运行查询。


改进的表设计将删除

id
并使用该单词作为主键(假设它们是唯一的)。我添加了大约 1000 个单词并分析了表格。

create table words ( word text primary key );

copy words(word) from '/Users/schwern/tmp/words.txt';

analyze words;

您的所有查询都执行仅索引扫描。

默认的 B-Tree 索引可以进行精确匹配 (

words = 'this'
)、尾随通配符 (
words like 'this%'
) 和排序。我们可以使用 trigram ops 进一步添加 Gist 索引来改进这一点。

create index word_gin_idx on words using gist(word gist_trgm_ops);
现在诸如

word like '%this%'

之类的查询将使用Gist索引。


0
投票
我有点惊讶它不只是工作,至少在 C 排序规则中。但我可以证实它不是。

您可以以同样的方式手动重写查询

word like 'abc%'

有时会被重写:

explain analyze select * from words where word >='abc' and word <'abd'
但这只能保证在 C 排序规则中给出相同的答案。

顺便说一句,您应该使用 EXPLAIN ANALYZE 检查分区修剪。分区修剪可能仅在运行时发生,在这种情况下,所有分区仍显示在计划 EXPLAIN 计划中。 (但运行时修剪不是这里的情况,我查了一下)

© www.soinside.com 2019 - 2024. All rights reserved.