【发布时间】:2014-11-19 17:46:53
【问题描述】:
我在 PostgreSQL 9.2 中有一个表,它有一个 text 列。我们称之为text_col。此列中的值相当独特(最多可能包含 5-6 个重复项)。该表有大约 500 万行。这些行中大约有一半包含text_col 的null 值。当我执行以下查询时,我期望 1-5 行。在大多数情况下 (>80%) 我只希望有 1 行。
查询
explain analyze SELECT col1,col2.. colN
FROM table
WHERE text_col = 'my_value';
btree 索引存在于 text_col。查询计划器从不使用此索引,我不知道为什么。这是查询的输出。
规划师
Seq Scan on two (cost=0.000..459573.080 rows=93 width=339) (actual time=1392.864..3196.283 rows=2 loops=1)
Filter: (victor = 'foxtrot'::text)
Rows Removed by Filter: 4077384
我添加了另一个部分索引来尝试过滤掉那些不为空但没有帮助的值(有或没有text_pattern_ops。我不需要text_pattern_ops,考虑到没有LIKE条件在我的查询,但它们也匹配相等)。
CREATE INDEX name_idx
ON table
USING btree
(text_col COLLATE pg_catalog."default" text_pattern_ops)
WHERE text_col IS NOT NULL;
使用set enable_seqscan = off; 禁用序列扫描会使规划器仍然选择seqscan 而不是index_scan。总之……
- 此查询返回的行数很少。
- 鉴于非空行相当独特,对文本的索引扫描应该更快。
- 清空和分析表并不能帮助优化器选择索引。
我的问题
- 为什么数据库选择顺序扫描而不是索引扫描?
- 当表中的文本列应检查其相等条件时,我是否可以遵循任何最佳做法?
- 如何减少此查询所用的时间?
[编辑 - 更多信息]
- 索引扫描是在我的本地数据库中提取的,该数据库包含生产中可用数据的大约 10%。
【问题讨论】:
-
我认为排序规则不匹配。尝试指定一个:
SELECT col1,col2.. colN FROM table WHERE text_col = 'my_value' COLLATE pg_catalog."default" -
我尝试指定
COLLATE pg_catalog."default",结果是序列扫描。 -
表结构(CREATE TABLE 语句)?我 a) 建立了一个测试表,b) 用 500 万行、一半 NULL 和一半随机字符串填充它,c) 在 text_col 上创建了一个部分索引,d) 分析了表,并且 e) 在 0.075 毫秒内找到了一个匹配的行。 PostgreSQL 9.3 使用了仅索引扫描。
-
我使用 Postgresql 9.2.4。我发现它会选择序列扫描同样令人费解。
-
因为您一直在尝试禁用规划器方法。
show enable_indexscan;能得到什么?你不是不小心禁用的吗?
标签: sql database performance postgresql indexing