运行 Heroku “Crane” PostgreSQL 实例(版本 9.1.6)
我有一张销售点表;货币金额以当地货币计算。我有一个货币换算表,其中包含任何给定日期的每种货币和欧元之间的换算系数。我想总结给定书籍(产品)的销售额、退货、赠品和收入(以美元计)。所以我加入了货币兑换表,一次将当地货币兑换成欧元,然后再次将欧元兑换成美元(请记住,汇率根据销售的结算日期而有所不同)。因此,每个要考虑的销售点都将两次加入货币兑换;实验告诉我,这是主要的减速因素。
所以我正在尝试优化以下查询:
SELECT
sum(paid_sales - paid_returns) as paid_units,
sum(royalty_amt*(uu_cc.rate / sp_cc.rate)) as royalty_amt,
sum(free_sales - free_returns) as free_units,
sum(lent_units) as lent_units
FROM "sales_points"
join currency_conversions sp_cc
on sp_cc.date = sales_points.settlement_date
and sp_cc.currency = sales_points.currency
join currency_conversions uu_cc
on uu_cc.date = sales_points.settlement_date
and uu_cc.currency = 'USD'
WHERE "sales_points"."book_id" = 234
LIMIT 1
我创建了以下索引:
CREATE INDEX index_currency_conversions_on_date_and_currency
ON currency_conversions
USING btree (date, currency COLLATE pg_catalog."default");
然而 EXPLAIN(在运行 ANALYZE 之后)告诉我它正在对货币转换表进行顺序扫描。如果它很重要,date
则为“日期”currency
类型并且为“char var(255)”类型。
这是查询计划:
Limit (cost=7285.04..7285.04 rows=1 width=39) (actual time=103.166..103.167 rows=1 loops=1)
Buffers: shared hit=916
-> Aggregate (cost=7285.04..7285.04 rows=1 width=39) (actual time=103.163..103.163 rows=1 loops=1)
Buffers: shared hit=916
-> Hash Join (cost=584.15..7256.29 rows=6388 width=39) (actual time=60.513..92.084 rows=5840 loops=1)
Hash Cond: (sp_cc.date = uu_cc.date)
Buffers: shared hit=916
-> Hash Join (cost=351.63..6985.45 rows=6388 width=39) (actual time=52.454..72.418 rows=5840 loops=1)
Hash Cond: ((sales_points.settlement_date = sp_cc.date) AND ((sales_points.currency)::text = (sp_cc.currency)::text))
Buffers: shared hit=763
-> Bitmap Heap Scan on sales_points (cost=54.09..6630.06 rows=6446 width=30) (actual time=0.912..7.020 rows=5840 loops=1)
Recheck Cond: (book_id = 234)
Buffers: shared hit=610
-> Bitmap Index Scan on index_sales_points_on_book_id (cost=0.00..53.77 rows=6446 width=0) (actual time=0.809..0.809 rows=6521 loops=1)
Index Cond: (book_id = 234)
Buffers: shared hit=22
-> Hash (cost=214.95..214.95 rows=20649 width=16) (actual time=51.502..51.502 rows=20649 loops=1)
Buckets: 4096 Batches: 1 Memory Usage: 968kB
Buffers: shared hit=153
-> Seq Scan on currency_conversions sp_cc (cost=0.00..214.95 rows=20649 width=16) (actual time=0.007..21.153 rows=20649 loops=1)
Buffers: shared hit=153
-> Hash (cost=225.27..225.27 rows=2071 width=12) (actual time=8.040..8.040 rows=2071 loops=1)
Buckets: 1024 Batches: 1 Memory Usage: 89kB
Buffers: shared hit=153
-> Seq Scan on currency_conversions uu_cc (cost=0.00..225.27 rows=2071 width=12) (actual time=0.021..5.963 rows=2071 loops=1)
Filter: ((currency)::text = 'USD'::text)
Buffers: shared hit=153
Total runtime: 103.306 ms
有谁知道为什么它不使用我的索引?