我有以下查询,目前正在运行大约450毫秒:
SELECT stripe_balance_transactions.created, fee, stripe_charges.plan
FROM stripe_balance_transactions
JOIN stripe_charges ON stripe_balance_transactions.source = stripe_charges.stripe_id
WHERE
stripe_balance_transactions.account_id = 93
AND (stripe_balance_transactions.type = 'charge' AND stripe_charges.refunded = false)
AND (stripe_charges.invoice IS NOT NULL)
AND (stripe_balance_transactions.created BETWEEN '2013-01-20 00:00:00.000000' AND '2014-02-19 23:59:59.999999')
ORDER BY stripe_balance_transactions.created;
我是否可以使用其他索引来尝试加快查询速度?
以下是EXPLAIN ANALYZE
的输出:
Sort (cost=30742.84..30748.08 rows=2096 width=25) (actual time=456.942..457.082 rows=1579 loops=1)
Sort Key: stripe_balance_transactions.created
Sort Method: quicksort Memory: 138kB
-> Hash Join (cost=24408.50..30627.21 rows=2096 width=25) (actual time=360.555..455.798 rows=1579 loops=1)
Hash Cond: ((stripe_balance_transactions.source)::text = (stripe_charges.stripe_id)::text)
-> Bitmap Heap Scan on stripe_balance_transactions (cost=75.16..3924.19 rows=2016 width=30) (actual time=0.756..1.644 rows=1610 loops=1)
Recheck Cond: ((account_id = 93) AND ((type)::text = 'charge'::text) AND (created >= '2013-01-20 00:00:00'::timestamp without time zone) AND (created <= '2014-02-19 23:59:59.999999'::timestamp without time zone))
-> Bitmap Index Scan on index_balance_transactions_account_type_created (cost=0.00..74.66 rows=2016 width=0) (actual time=0.732..0.732 rows=1610 loops=1)
Index Cond: ((account_id = 93) AND ((type)::text = 'charge'::text) AND (created >= '2013-01-20 00:00:00'::timestamp without time zone) AND (created <= '2014-02-19 23:59:59.999999'::timestamp without time zone))
-> Hash (cost=18027.34..18027.34 rows=326080 width=31) (actual time=358.523..358.523 rows=216688 loops=1)
Buckets: 2048 Batches: 32 Memory Usage: 423kB
-> Seq Scan on stripe_charges (cost=0.00..18027.34 rows=326080 width=31) (actual time=0.065..233.197 rows=216688 loops=1)
Filter: ((NOT refunded) AND (invoice IS NOT NULL))
Rows Removed by Filter: 131346
Total runtime: 457.260 ms
(15 rows)
我正在运行Postgres 9.3.1。
编辑:这是当前的索引......
# stripe_charges #
"stripe_charges_pkey" PRIMARY KEY, btree (id)
"index_account_ref_created_plan" btree (account_id, refunded, created, plan)
"index_stripe_charges_on_account_id" btree (account_id)
"index_stripe_charges_on_account_id_and_amount" btree (account_id, amount)
"index_stripe_charges_on_account_id_and_amount_and_created" btree (account_id, amount, created)
"index_stripe_charges_on_account_id_and_paid_and_created" btree (account_id, paid, created)
"index_stripe_charges_on_account_id_and_stripe_id" btree (account_id, stripe_id)
"index_stripe_charges_on_customer" btree (customer)
"index_stripe_charges_on_invoice" btree (invoice)
"index_stripe_charges_on_is_projected" btree (is_projected)
"index_stripe_charges_on_is_projected_and_projected" btree (is_projected, projected)
"index_stripe_charges_on_parent_charge" btree (parent_charge)
"index_stripe_charges_on_plan" btree (plan)
"index_stripe_charges_on_projected" btree (projected)
"index_stripe_charges_on_refunded" btree (refunded)
"index_stripe_charges_on_stripe_id" btree (stripe_id)
# stripe_balance_transactions #
"stripe_balance_transactions_pkey" PRIMARY KEY, btree (id)
"index_balance_transactions_account_type_created" btree (account_id, type, created)
"index_stripe_balance_transactions_on_account_id" btree (account_id)
"index_stripe_balance_transactions_on_account_id_and_stripe_id" btree (account_id, stripe_id)
"index_stripe_balance_transactions_on_plan" btree (plan)
"index_stripe_balance_transactions_on_source" btree (source)
"index_stripe_balance_transactions_on_stripe_id" btree (stripe_id)
"index_stripe_balance_transactions_on_type" btree (type)
答案 0 :(得分:1)
重新格式化查询后,应将created
上的条件重写为:
SELECT b.created, fee, c.plan
FROM stripe_charges c
JOIN stripe_balance_transactions b ON b.source = c.stripe_id
WHERE c.refunded = FALSE
AND c.invoice IS NOT NULL
AND b.account_id = 93
AND b.type = 'charge'
AND b.created >= '2013-01-20 00:00'
AND b.created < '2014-02-20 00:00'
ORDER BY b.created;
为了获得最佳性能,您可以沿着这些方向使用partial, multicolumn covering indexes:
CREATE INDEX foo_idx ON stripe_charges (stripe_id, fee, plan)
WHERE refunded = FALSE
AND invoice IS NOT NULL;
CREATE INDEX bar_idx ON stripe_balance_transactions (account_id, source, created)
WHERE type = 'charge';
但是,如果不了解所有细节,这是在黑暗中刺伤。从昨天开始考虑dba.SE上的这个相关答案,其中包含覆盖索引的更多信息和链接:
Very slow execution of a simple query
在评论中作为@bma suggested:测试是否实际使用了所有索引。您可以查看pg_stat_user_indexes
,或者如果您应该使用pgAdmin,请点击&#34;统计&#34;选项卡(右上角)用于索引或表的索引集合。