3

我有一个非常简单的查询,基本上是这样的:

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(布尔值)的整数,但这对性能没有影响(我猜是因为 = 1 仍然会带回很多行?)

4

1 回答 1

2

索引不会帮助你。我认为您需要找到一种更好的方法来巩固您的删除。

您说运行需要 39 秒,但您提供的实际查询计划需要 15 毫秒才能运行,这大约是 2000 的因数。我很难想象缓存会有这么大帮助的情况,除非我们谈论的是具有大量 TOASTed 值的非常宽的表。这告诉我,实际问题不在您的选择中,而是在您的管道中的其他地方。这可能包括往返费用,但是您正在执行删除操作。

我的建议是查看报表合并。这意味着避免往返并尽可能多地将逻辑推送到单个查询中。由于您还没有发布完整的上下文,我建议您可能想要研究可写的 CTE,以便在没有往返的情况下一起批量插入、更新和删除。

于 2013-03-07T04:11:15.667 回答