为什么postgres没有使用类似'CONSTANT_PREFIX_%'标准的BTree索引?

时间:2016-02-12 15:52:28

标签: postgresql

我有一个带有B-Tree索引的表:

CREATE INDEX idx_test_report_accession on test_report (accession);

我使用explain运行以下查询:

"QUERY PLAN"
"Seq Scan on public.test_report r  (cost=0.00..705829.12 rows=30694 width=1140) (actual time=0.143..6253.818 rows=11094 loops=1)"
"  Output: detected_transcript_translation_id, peptide_spectrum_match_id, accession, peptide, modified_sequence, var_mod, spectrum_title, spectrum_file, confidence, mz, retention_time, precursor_mz_error_ppm, sample_name, transcript, gene_symbol, prot_seq, ref_based_location, external_identifier, experiment_name, report_filename, line_number, experiment_path"
"  Filter: (r.accession ~~ 'IP_%'::text)"
"  Rows Removed by Filter: 4296116"
"Planning time: 1.331 ms"
"Execution time: 6255.560 ms"

似乎认为表中只有30694行,并决定不使用索引。鉴于类似的通配符是后缀,我认为没有理由不使用索引...

行数为:

SELECT count(*) from test_report r;
4307210

匹配行的数量非常小:

SELECT count(*) from test_report r WHERE r.accession like 'IP_%';
11094

注意:

  • Postgres版本是9.4

1 个答案:

答案 0 :(得分:5)

在许多归类中,共享相同前缀的单词可能不会按排序顺序彼此相邻。例如See here。这意味着具有这些排序规则的索引无法有效地用于完成前缀查询。

除非您的数据库归类是“C”,否则您的默认索引将无法用于前缀搜索。您可以手动指定要在支持它的索引中使用的排序规则或运算符类:

create index on foobar (x collate "C");

create index on foobar (x text_pattern_ops);

我只是使用“C”排序规则创建所有数据库(即使您需要使用UTF8编码,也可以这样做)。有些人不喜欢它的排序方式,但这主要是由于区分大小写。没有人曾向我抱怨过“嘿,你需要按en_US.UTF-8排序规则排序”。这可能是因为几乎没有人知道这些规则是什么。