【问题标题】:PostgreSQL: Why is this query not using my index?PostgreSQL:为什么这个查询不使用我的索引?
【发布时间】:2014-01-22 06:37:38
【问题描述】:

我正在对数据库执行此查询(所有数字和列名都是组成的):

select * from t where a=1 and b=11 and c!=5 and d<8

t 有一个索引:

create index i on t (a,b,c,d)

当我运行“EXPLAIN ANALYZE”时,查询会执行顺序扫描,并且执行此操作大约需要 55 毫秒。如果我像这样修改查询:

select * from t where a=1 and b=11 and c=5 and d<8
                                       ^

它使用索引并在 0.5 毫秒内完成。所以它一定是不等于,对吧?不是这样,因为如果我做这个查询:

select * from t where a=1 and b=11 and c=5 and d!=8
                                               ^

查询仍然使用索引。但是如果我尝试这个,没有索引:

select * from t where a=1 and b=11 and c<5 and d<8
                                       ^

那么为什么 Postgres 会这样呢?这对我来说很奇怪。

【问题讨论】:

    标签: sql postgresql indexing


    【解决方案1】:

    正如您已经意识到的那样,问题与使用除等于以外的运算符有关。索引只能最有效地用于与等于(加上一个范围条件)比较的最左边的列。

    在你的例子中:

    create index i on t (a,b,c,d);
    where a=1 and b=11 and c!=5 and d<8;
    

    它只能有效地使用ab 的索引。这意味着数据库会获取与ab 条件匹配的所有行,然后根据剩余条件检查每一行。

    当您将 c 上的过滤器更改为 equals 时,它会(可能)获取更少的行(仅匹配 abc 的那些),然后根据 @987654332 检查那些(更少)行@ 筛选。在这种情况下使用索引效率更高。

    一般来说,PostgreSQL 查询规划器评估两个选项:(1) 使用索引; (2) 进行 SeqScan。对于两者,它都会计算成本值——它越高,预期的性能就越差。因此,它采用成本价值较小的那个。这是它决定使用或不使用索引的方式,没有固定的阈值。

    最后,上面写着“加一个范围条件”。这意味着它不仅可以在使用等号时以最有效的方式使用索引,而且还可以用于单个范围条件。

    考虑到您的查询中只有一个范围条件,我建议您像这样更改索引:

    create index i on t (a,b,d,c);
    

    现在它可以通过索引有效地使用abd 上的过滤器,并且只需要过滤掉c!=5 所在的行。虽然这个索引可以更有效地用于您的查询作为您的原始索引,但这并不意味着 PG 会自动使用它。这取决于成本估算。不过试试看吧。

    最后,如果这还不够快并且您在表达式c!=5 中使用的值5 是常量,您可以考虑使用部分索引:

     create index i on t (a,b,d)
            where c!=5;
    

    如果您比较它们的值是常量,您也可以对所有其他列执行此操作。

    参考资料:

    【讨论】:

      【解决方案2】:

      我会说它不会将索引用于第一个查询,因为索引并没有真正帮助,因为几乎整个表都匹配。在这种情况下,扫描整个表会更快。最后两个查询之间的区别在于,可能仅在预期结果大小低于某个阈值时才使用索引。一个完全匹配的查询很可能比使用 less 的查询产生更少的结果,而使用 less 的查询仍然产生少于不等于的选择。

      话虽如此,查询优化器是一款高度复杂的软件,并且经常会产生令人惊讶的结果。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-10-05
        • 1970-01-01
        • 1970-01-01
        • 2011-08-24
        相关资源
        最近更新 更多