sql - PostgreSQL 多列索引连接与比较 ("<"和 ">") 运算符

标签 sql optimization postgresql indexing

我正在尝试利用 PostgreSQL 中的多列 btree 索引来执行两个表之间令人讨厌的连接。

               Table "revision_main"
     Column     |          Type          | Modifiers 
----------------+------------------------+-----------
 revision_id    | integer                | 
 page_id        | integer                | 

Indexes:
    "revision_main_pkey" UNIQUE, btree (revision_id)
    "revision_main_cluster_idx" btree (page_id, "timestamp") CLUSTER

此表包含对 wiki 中页面的修订(约 3 亿行)。我的表中还有更多列,但在本示例中我已将它们丢弃,因为它们无关紧要。

               Table "revert"
       Column       |  Type   | Modifiers 
--------------------+---------+-----------
 page_id            | integer | 
 revision_id        | integer | 
 reverted_to        | integer | 
Indexes:
    "revert_page_between_idx" btree (page_id, reverted_to, revision_id) CLUSTER

此表包含还原修订(约 2200 万行)。如果修订已被还原,则 revision_id 将在 revision_main 表中有一行,其 revision_id 将介于 reverted_to 和 revision_id 之间,并共享相同的 page_id。 (如果您好奇,请参阅 http://en.wikipedia.org/wiki/Wikipedia:Revert。)

连接这两个表以获得恢复的修订似乎很简单。这是我想出的:

explain SELECT
    r.revision_id,
    rvt.revision_id
FROM revision_main r
INNER JOIN revert rvt 
    ON r.page_id = rvt.page_id 
    AND r.revision_id > rvt.reverted_to
    AND r.revision_id < rvt.revision_id;
                                       QUERY PLAN                                               
----------------------------------------------------------------------------------------------------
 Merge Join  (cost=4202878.87..15927491478.57 rows=88418194298 width=8)
   Merge Cond: (r.page_id = rvt.page_id)
   Join Filter: ((r.revision_id > rvt.reverted_to) AND (r.revision_id < rvt.revision_id))
   ->  Index Scan using revision_main_page_id_idx on revision_main r  (cost=0.00..9740790.61 rows=223163392 width=8)
   ->  Materialize  (cost=4201592.06..4536465.21 rows=26789852 width=12)
         ->  Sort  (cost=4201592.06..4268566.69 rows=26789852 width=12)
               Sort Key: rvt.page_id
               ->  Seq Scan on revert rvt  (cost=0.00..438534.52 rows=26789852 width=12)

即使恢复时的聚集索引应该是 Btree 索引(因此支持比较运算符,如“<”和“>”),查询优化器不会使用索引进行连接,并且“解释”会预测总成本超过 150 亿(明年可能完成)。

是否无法将比较运算符用于多列(btree)索引?我只是做错了吗?

最佳答案

看起来优化器比您更了解它的工作。

如果您选择的不仅仅是表的一小部分(这部分取决于硬件,比如说 5%),那么选择和排序整个表比使用索引更快。如果您只是选择几行,那么它应该使用索引。因此它为您的数据提供了正确的查询计划。

至于总成本,这些数字都是废话,只有在单个查询中相互比较时才有用。 (两个非常相似的查询产生的总成本可能在非常不同的规模上。)执行时间和查询成本几乎无关。

关于sql - PostgreSQL 多列索引连接与比较 ("<"和 ">") 运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4891172/

相关文章:

linux - postgresql:读取器进程消耗高 cpu

php - 我没有从 SQL 查询中得到预期的结果

sql - 数据库编程概念

mysql - 如何从数据库中检索至少存在 10 个列值中的 3 个的记录?

linux - 如何在oracle linux 7.2中安装postgresql

sql - Postgres : limit by the results of a sum function

MySql 统计失败代码的出现次数

hibernate - 使用 Hibernate 的 Oracle 优化器提示

c# - x86 CPU 执行哪些类型的重新排序优化?

c - 读取大数据时有没有比 fscanf 更快的方法