只使用b树的Postgres - 为什么?

时间:2014-10-22 07:07:07

标签: sql postgresql

索引:

CREATE INDEX message_index ON message(queue_id, target_client_id, timestamp ASC, source_client_id);

查询:

EXPLAIN ANALYZE SELECT content FROM message WHERE message.queue_id = 5 AND message.source_client_id = 5 AND (message.target_client_id = -1 OR message.target_client_id = 5) ORDER BY timestamp ASC LIMIT 1;

输出:

 Sort  (cost=8.39..8.39 rows=1 width=13) (actual time=0.014..0.014 rows=0 loops=1)
   Sort Key: "timestamp"
   Sort Method: quicksort  Memory: 25kB
   ->  Index Scan using message_index on message  (cost=0.27..8.38 rows=1 width=13) (actual time=0.011..0.011 rows=0 loops=1)
         Index Cond: ((queue_id = 5) AND (source_client_id = 5))
         Filter: ((target_client_id = (-1)) OR (target_client_id = 5))
 Total runtime: 0.034 ms

为什么postgres在开始时执行快速排序,为什么它不使用索引中的timestamp属性?什么(...... rows = 1)是什么意思?

2 个答案:

答案 0 :(得分:2)

排序在结束完成,而不是在开头。

您必须从最内层节点(Index Scan using message_index on message开始,然后“上升树”开始阅读执行计划。

所以执行顺序是

  1. 从索引
  2. 中检索行
  3. 使用timestamp列对检索到的行进行排序(btw是列的可怕名称)
  4. 第一对括号中的rows=1表示Postgres 期望(估计)此步骤仅返回一行。第二部分中的row=0表示实际上没有基于where条件返回的行。

    手册中说明了输出的各个部分:
    http://www.postgresql.org/docs/current/static/using-explain.html

    您还可以阅读本网站提供的信息:
    http://use-the-index-luke.com/

答案 1 :(得分:0)

它不能使用索引来提供排序,因为target_client_id在索引定义中位于timestamp之前,并且在where子句中未指定target_client_id与单个值相等。< / p>

理论上,这样的索引可用于通过执行两个索引扫描来提供排序,每个索引扫描对应于target_client_id的每个指定值,以便为每个索引扫描获取行。然后它将合并两个有序流。但PostgreSQL并没有编写这种类型的优化。 (在这种情况下,它可能实际上不是优化。)

是的,如果它返回超过1行的话就会排序。