sql - 如果索引用于查询,PostgreSQL 将不会使用索引进行投影

标签 sql database postgresql optimization indexing

我一直在进行一些实验,标题中的陈述似乎是正确的,我想知道是否有解决办法。

这是一个例子:

CREATE TABLE test ( cond text, v1 integer, v2 integer, v3 integer );
-- Insert millions of rows
CREATE INDEX cond_idx ON test (cond);
CREATE INDEX values_idx ON test (v1, v2, v3);
VACUUM ANALYZE test;

运行这些查询:

-- Uses Index Only Scan on values_idx for projection
SELECT sum(v1), sum(v2), sum(v3) FROM test;
-- Uses Bitmap Index Scan on cond_idx then a Bitmap Heap Scan
-- This is undesirable as it doesn't rely exclusively on indexes
SELECT sum(v1), sum(v2), sum(v3) FROM test WHERE cond = '123';

PostgreSQL 可以有效地组合索引,但它似乎只适用于复合条件,有没有办法让 PostgreSQL 在使用一个或多个索引来查找所需的行后使用索引进行投影?

自动响应是创建一个包含所有 4 列的索引。问题是这只是一个简约的例子。在实际场景中,同一张表会被不同的列查询,需要针对每个需要的查询条件使用多列索引。

更新:将计数更改为总和以使示例更易于理解。还添加了更多“值(value)”列。

最佳答案

count() 聚合不能使用索引数据作为输入,因为它对每个非空值计数 1:http://www.postgresql.org/docs/9.4/static/functions-aggregate.html

count(expression): 
    number of input rows for which the value of expression is not null

在第二个查询中,经过索引过滤后,我们不知道哪一行有一个空的value列。

您只需要将相关数据添加到索引中并使用多列索引即可。

CREATE INDEX cond_value_idx ON test (cond, value);

一旦您阅读了优秀的 http://use-the-index-luke.com/,这可能会变得清晰

这是一个类比,可以更好地了解 PostgreSQL 的内部结构。 您有 1000 本普通书籍和 2 本“特殊”书籍。 1000 本书是您的行,另外 2 本书是您的索引。

索引书的一个是按主题分类列出每个书架和编号,另一个是按作者分类列出每个书架和编号。

请注意,这 1000 本书存放在一个巨大的书架上,而 2 本索引书就放在您的 table 上,随时可以使用。

问题是有些书非常独特,以至于它们没有按主题分类(我们的空值)。

如果你想统计有主题关联的书籍,你只需要选择“主题”索引。 但是,如果您想统计 Gregory Smith 的每一本具有相关主题的书籍,您将在作者索引中查找 Gregory Smith 的书籍,然后在书架上挑选它们以查看它们是否有主题。

这里的解决方案是第三个索引书,它列出了每个书架和编号,按作者分类,然后按主题分类。只有这样,您才能立即回答问题,而无需去货架。

请注意,多列索引的顺序很重要,因为您无法像按主题分类然后按作者分类的索引书那样轻松地回答相同的问题。

关于sql - 如果索引用于查询,PostgreSQL 将不会使用索引进行投影,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30016601/

相关文章:

sql - Postgres 跨表唯一组合约束

windows - 使用 npm 安装 postgres 问题

ruby-on-rails - 如何在 Mac 上已创建的 Rails 应用程序中安装 postgresql?

sql - 当一行具有 MAX 值时,获取它的字符串值 "Yes"?

c# - 一个 DELETE 查询,如何知道没有要删除的内容?

mysql - 我应该在这个例子中使用外键吗?

database - Windows Phone 7 数据库

android - 将 EditText 中的 int 类型变量插入到 Android 中的 SQL 数据库中

mysql - 从表中选择最后 n 行Chubb

mysql - 有没有办法重置 mysql IDLE/Sleep 连接?