我正在执行大量的 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
最佳答案
从给定的数字来看,您的替代查询(“如果我不间断地按价格排序”)实际上慢,并且您误读了数字。 0.079 ms
与 0.42
(?).
这也是有道理的,因为您的第一个查询与索引的排序顺序完全匹配。
您已经有了完美的索引。建议删除price
是没有根据的。附加列删除了排序步骤的成本:time=0.055..0.055
正如您在计划中看到的那样。
无论哪种方式,它都应该无关紧要。一旦您将检索到的行数减少到一个小数(在索引的前导列上使用谓词),无论哪种方式,其余的都是便宜的。
要获得更有趣的结果,请不要使用 stops < 2
进行测试(只留下 0 和 1 个停止点),尝试使用更大的数字来查看任何(可能很小的)差异。
实际上,由于几乎所有列都已经在索引中,我会尝试添加一个缺失的列 id
,也是-如果你能得到index-only scans出于这个(Postgres 9.2+,阅读链接页面上的 Postgres Wiki):
CREATE INDEX my_idx ON flights (outbound, inbound, date, stops, price, <b>id</b>);
SELECT id, outbound, inbound, date, stops, price
FROM ...
关于sql - 如何通过 order by 降低 sql select 的成本?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27545743/