我们在巨大的桌子上使用单列索引来尝试快速 '选择不同的'在专栏上。
这曾经工作得很好,但......已经不行了。我们不知道是什么 发生了。
以下是事实:
请求:
SELECT dwhinv___rfovsnide::varchar
FROM dwhinv
WHERE dwhinv___rfovsnide > '201212_cloture'
ORDER BY dwhinv___rfovsnide LIMIT 1
模仿'不同,我们多次播放此查询,每次更改dwhinv___rfovsnide值以获取下一个值。
正常查询时间小于1毫秒。
计划:
Limit (cost=0.00..1.13 rows=1 width=12) (actual time=5798.915..5798.916 rows=1 loops=1)
-> Index Scan using vsn_idx on dwhinv (cost=0.00..302591122.05 rows=267473826 width=12) (actual time=5798.912..5798.912 rows=1 loops=1)
Index Cond: ((dwhinv___rfovsnide)::text > '201212_cloture'::text)
Total runtime: 5799.141 ms
default_statistics_target = 200;
postgresql版本8.4
使用的索引:
CREATE INDEX vsn_idx
ON dwhinv
USING btree (dwhinv___rfovsnide);
该计划仅从5798.912开始! 解释仅在1毫秒以内,所以这不是计划选择的时间。 该列有26个不同的值。 该指数一直是 新鲜的重建。
可能是什么问题?
答案 0 :(得分:0)
感谢您的评论和pgperf邮件列表,我们发现了问题。
计划开始时的延迟是从索引获取第一行的时间,因此它实际上与索引读数有关。
我的索引很新鲜,我的真空也是。 但是我们有一些疑问 IDLE in transation 女巫不允许真空做这项工作。
解释:
给出一个包含数百万行的表MY_TABLE,同样按列DATA_VERSION(每个10百万)重新分配,并在DATA_VERSION列上进行索引
- >第1步我播放一个留在 IDLE in transation
的查询- >第2步我删除来自MY_TABLE的所有行,其中DATA_VERSION = 100和200
- >步骤3我使用 vacuum :vacuum cant删除对版本为100&的行的引用200因为STEP 1仍然 IDLE in transation
- >第4步我使用DATA_VERSION上的索引在MY_TABLE 上进行查询以获取所有DATA_VERSION
- > 索引查看版本100 ,尝试获取第一行以确保它在表格中可见...它不是,再次尝试使用ALL OTHER ROW。 ......一切都消失了。桌面上的完整数据已经被读取了......很多秒钟的io都丢失了
解决方案:避免STEP 1永久停留以允许真空解除引用版本100&索引200