哪些索引有助于加快查询速度?

时间:2014-02-20 18:58:43

标签: sql performance postgresql

我有以下查询,目前正在运行大约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)

1 个答案:

答案 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;选项卡(右上角)用于索引或表的索引集合。

相关问题