我有一个非常简单的查询基本上是这样的:
Select * from my_table Where my_field != '';
表格中有大约40,000行,“my_field”列是文本字段(varchar 255)
查询大约需要39,000毫秒才能运行。我猜是因为它必须查看每个记录中的非空字符串。我已将my_field列编入索引,但它没有改变任何内容。
以防万一,这是查询计划:
"Seq Scan on my_table (cost=0.00..3468.91 rows=39744 width=459)"
" Filter: ((my_field)::text <> ''::text)"
这里最好的选择是什么?
解释分析:
"Seq Scan on my_table (cost=0.00..3468.91 rows=39730 width=459) (actual time=0.021..13.763 rows=39714 loops=1)"
" Filter: ((my_field)::text <> ''::text)"
"Total runtime: 14.856 ms"
我添加了这些索引
CREATE INDEX aa_idx ON my_table(my_field);
CREATE INDEX aa_idx ON my_table(my_field) WHERE my_field <> '';
这是Postgres 9.1
编辑:[2013-02-26 00:04GMT]
在“my_field”上创建分区作为检查约束会有什么好处吗?
类似CHECK(my_field ='')和分区2 CHECK(my_field!='')
我猜我的所有东西都是一张包含很多行的表格?但这是否意味着即使分区包含大约80%的数据,select!=''查询也会表现得更快?
我也研究过全文搜索,但这似乎是OTT。我还看了将列设为0或1(bool)的int,但这对性能没有影响(我猜是因为= 1仍会带回很多行?)
答案 0 :(得分:2)
索引对你没用。我认为你需要找到一种更好的方法来巩固你的删除。
你说它需要39秒才能运行,但你提供的实际查询计划需要15毫秒才能运行,这大概是2000关。我无法想象一个缓存会对此有所帮助的情况,除非我们讨论的是具有大量TOASTed值的非常宽的表。这告诉我实际问题不在您的选择中,而在您的管道中的其他地方。这可能包括往返费用,但您正在进行删除。
我的建议是查看合并声明。这意味着避免往返,并尽可能多地将逻辑推送到单个查询中。由于您尚未发布完整的上下文,我建议您可以查看可写入的CTE,以便在不进行往返的情况下一起批量插入,更新和删除。