如何通过订单减少sql select的成本?

时间:2014-12-18 11:40:47

标签: sql database postgresql

我正在执行大量的SQL选择,如下所示。想象一下,我们有一个包含航班的数据库,每个航班当然可能有出境和入境机场,出发日期,出发地和目的地之间的停靠点数(长途航班),当然还有价格。

我现在想要选择一条特定路线,并选择停靠次数最少的路线,当然还有最优价路线。

CREATE TABLE flights(
    id integer
    outbound character varying,
    inbound character varying,
    date timestamp,
    stops integer
    price numeric
);
CREATE INDEX my_idx ON flights (outbound, inbound, date, stops, price);

select * from flights where outbound = 'SFO' and inbound = 'SYD' and date = '2015-10-10' and stops < 2 order by stops asc, price asc.

问题:使用explain-analyze的费用非常高:

Sort  (cost=9.78..9.79 rows=1 width=129) (actual time=0.055..0.055 rows=4 loops=1)
  Sort Key: stops, price
  Sort Method: quicksort  Memory: 26kB
  ->  Index Scan using my_idx  (cost=0.42..9.77 rows=1 width=129) (actual time=0.039..0.041 rows=4 loops=1)
        Index Cond: ((date = '2015-10-10'::date) AND ((outbound)::text = 'SFO'::text) AND (stops < 2) AND ((inbound)::text = 'SYD'::text))
Total runtime: 0.079 ms

如果我只是不停地按价格排序,那么成本是可以的(0.42)。但以停靠方式排序会增加成本显着。

如何降低成本?

postgresql 9.3.2

3 个答案:

答案 0 :(得分:5)

根据给定的数字判断,您的备用查询(“如果我只是按价格排序而不停止”)实际上是较慢,并且您误读了这些数字。 0.079 ms0.42(?)。

这也是有道理的,因为你的第一个查询完全符合索引的排序顺序。

您已拥有完美索引。删除price的建议没有根据。附加列会删除排序步骤的费用:time=0.055..0.055,如您在计划中所见。

无论哪种方式,它根本不重要。只要您将检索到的行数减少到 small 数字(在索引的前导列上有谓词),其余的都是便宜的。

要获得更有趣的结果,请不要使用stops < 2(只留下0和1站点)进行测试,尝试使用更大的数字来查看任何(可能很小的)差异。

实际上,由于几乎所有列都已在索引中,我也会尝试添加一个缺少的列id - 如果你可以从中获取index-only scans(Postgres 9.2+,请阅读链接页面上的Postgres Wiki:

CREATE INDEX my_idx ON flights (outbound, inbound, date, stops, price, id);
SELECT id, outbound, inbound, date, stops, price
FROM ...

答案 1 :(得分:2)

这是您的查询:

select * 
from flights
where outbound = 'SFO' and inbound = 'SYD' and date = '2015-10-10' and stops < 2
order by stops asc, price asc.

最佳指数为:flights(outbound, inbound, date, stops)。这适用于where子句。鉴于order by,我不知道是否有办法消除where,但除非当天有数千个航班,否则排序不应该是一个大问题。

答案 2 :(得分:0)

费用是任意数字。

此外,排序步骤的数字是进入和退出该步骤时计划中的总累积成本,而不是与该单个步骤相关的特定成本

您的查询可以快速排序。它只有四行,它以0.079毫秒完成整个查询。