2012-07-11 95 views
2

我們在同一個表上有2個相同的(雙精度)列,其中2個相同的索引運行2個相同的查詢。但其中一個比另一個快近10倍。這是什麼原因造成的?PostgreSQL索引查詢速度不一致

1) SELECT MIN("reports"."longitude") AS min_id FROM "reports" WHERE (area2 = 18) 

2) SELECT MIN("reports"."latitude") AS min_id FROM "reports" WHERE (area2 = 18) 

1 28ms運行,並在> 300毫秒

這裏2個運行是 '解釋':
1)

Result (cost=6.07..6.08 rows=1 width=0)" 
InitPlan 1 (returns $0)" 
    -> Limit (cost=0.00..6.07 rows=1 width=8)" 
     -> Index Scan using longitude on reports (cost=0.00..139617.49 rows=22983 width=8)" 
      Index Cond: (longitude IS NOT NULL)" 
      Filter: (area2 = 18)" 

2)

Result (cost=5.95..5.96 rows=1 width=0)" 
InitPlan 1 (returns $0)" 
    -> Limit (cost=0.00..5.95 rows=1 width=8)" 
     -> Index Scan using latitude on reports (cost=0.00..136754.07 rows=22983 width=8)" 
      Index Cond: (latitude IS NOT NULL)" 
      Filter: (area2 = 18)" 

作爲要求這裏ED是在解釋分析輸出...

1)

Result (cost=6.07..6.08 rows=1 width=0) (actual time=10.992..10.993 rows=1 loops=1)" 
InitPlan 1 (returns $0)" 
    -> Limit (cost=0.00..6.07 rows=1 width=8) (actual time=10.985..10.986 rows=1 loops=1)" 
      -> Index Scan using longitude on reports (cost=0.00..139617.49 rows=22983 width=8) (actual time=10.983..10.983 rows=1 loops=1)" 
       Index Cond: (longitude IS NOT NULL)" 
       Filter: (area2 = 18)" 
Total runtime: 11.033 ms" 

2)

Result (cost=5.95..5.96 rows=1 width=0) (actual time=259.749..259.749 rows=1 loops=1)" 
InitPlan 1 (returns $0)" 
    -> Limit (cost=0.00..5.95 rows=1 width=8) (actual time=259.740..259.740 rows=1 loops=1)" 
      -> Index Scan using latitude on reports (cost=0.00..136754.07 rows=22983 width=8) (actual time=259.739..259.739 rows=1 loops=1)" 
       Index Cond: (latitude IS NOT NULL)" 
       Filter: (area2 = 18)" 
Total runtime: 259.789 ms" 
--------------------- 

這是怎麼回事?我怎樣才能讓第二個查詢正常運行並快速運行?據我所知,兩種設置都是相同的。

+0

你以前做過'VACUUM FULL ANALYZE'嗎?你做了一個'EXPLAIN ANALYSE'還是一個'EXPLAIN'? – ckruse 2012-07-11 16:27:05

+0

是否存在複合索引?請向我們展示表格定義和'explain analyze'的輸出 – wildplasser 2012-07-11 16:37:21

+1

您應該在這樣的問題中包含確切的表格和索引定義。哪些列是NOT NULL?索引大小? VACUUM FULL ANALYZE會改變什麼嗎? 'CLUSTER報告使用idx1'和'CLUSTER報告使用idx2'會改變什麼? (我期望它!) – 2012-07-11 18:45:36

回答

3

首先,不能保證索引加速查詢。其次,在進行性能考慮時,您需要多次運行每個查詢。加載索引並將頁面加載到緩存中可能會影響查詢的長度,因此會有開銷。

我不是Postgres的專家,但考慮到這一點,我並不感到驚訝。

查詢計劃正在循環查找索引,找到匹配area2 = 18的相應行,然後希望在第一個索引處停止(它使用索引,因此它可以從最低值開始向上移動) 。這是猜測它是如何工作的;我不知道Postgres完全是這樣做的。

在任何情況下,發生的情況是該區域比緯度指數開始時更接近經度指數的起點。因此,它首先找到第一個匹配的記錄。如果這個解釋是正確的,那麼與數據庫中的其他事物相比,這將表明該地區相對西部(較低經度)和相對北部(較高緯度)。

順便說一下,假設有很多區域,您可能會在Area2上得到更好的結果。

+0

感謝您的輸入 - 實際上有area2上的索引也 - 它似乎postgres選擇不使用它... – user1051849 2012-07-11 16:49:49

2

您正在進行索引掃描,但檢查的記錄數取決於您必須匹配area2條件才能匹配多少列表。

除非你的area2分佈很奇怪,爲了優化這個查詢,你應該在(area2, latitude)(area2, longitude)上放置複合索引。我懷疑你會得到< 10毫秒。 PG還可以使用其位圖堆掃描功能,將area2上的單獨索引與現有索引組合,以代替組合索引。