[英]Rails Slow Postgres Query with Order using Index
我正在對我的數據庫中的幾百萬個項目進行查詢,但是當我添加訂單時,查詢速度確實變慢。 這是我正在調用的代碼:
Post.where(source_id: source_ids_array).page(1).per(100).order("position asc, external_created_at desc")
(我正在使用Kaminari進行分頁)
這給了我以下sql:
Post Load (36537.8ms) SELECT "posts".* FROM "posts" WHERE "posts"."source_id" IN (17805, 18768, 20717, 17803, 17804, 18329, 20705, 19075, 19110, 19082, 18328) ORDER BY position asc, external_created_at desc LIMIT 100 OFFSET 0
但是,當我將查詢修改為:
Post.where(source_id: source_ids_array).page(1).per(100).order("position asc")
我得到以下sql:
Post Load (279.6ms) SELECT "posts".* FROM "posts" WHERE "posts"."source_id" IN (17805, 18768, 20717, 17803, 17804, 18329, 20705, 19075, 19110, 19082, 18328) ORDER BY position asc LIMIT 100 OFFSET 0
這是瘋狂的更快。
我在schema.db中的索引如下所示:
add_index "posts", ["external_created_at"], name: "index_posts_on_external_created_at", using: :btree
add_index "posts", ["position", "external_created_at"], name: "index_posts_on_position_and_external_created_at", using: :btree
add_index "posts", ["position"], name: "index_posts_on_position", using: :btree
如何加快查詢速度?
編輯:這是我的解釋分析:
Limit (cost=633132.80..633133.05 rows=100 width=891) (actual time=31927.725..31927.751 rows=100 loops=1)
-> Sort (cost=633132.80..635226.42 rows=837446 width=891) (actual time=31927.720..31927.729 rows=100 loops=1)
Sort Key: "position", external_created_at
Sort Method: top-N heapsort Memory: 78kB
-> Bitmap Heap Scan on posts (cost=19878.94..601126.22 rows=837446 width=891) (actual time=487.399..30855.211 rows=858629 loops=1)
Recheck Cond: (source_id = ANY ('{17805,18768,20717,17803,17804,18329,20705,19075,19110,19082,18328}'::integer[]))
Rows Removed by Index Recheck: 1050547
-> Bitmap Index Scan on index_posts_on_source_id (cost=0.00..19669.58 rows=837446 width=0) (actual time=485.025..485.025 rows=927175 loops=1)
Index Cond: (source_id = ANY ('{17805,18768,20717,17803,17804,18329,20705,19075,19110,19082,18328}'::integer[]))
Total runtime: 31927.998 ms
盡管其記錄不充分,但可以在創建索引時指定排序順序:
add_index :posts, [:external_created_at, :position],
order: { position: :asc, external_created_at: :desc }
如果然后運行rake db:structure:dump
我們可以看到它創建了以下SQL:
CREATE INDEX "index_posts_on_external_created_at_and_position"
ON "posts" ("external_created_at" DESC, "position" ASC);
請注意,我們不需要指定using: :btree
因為Postgres默認使用B-tree或name:
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.