pgsql挺好玩的,可以創建部分索引
部分索引的主要動機是爲了避免對普通數值(大量重複的數值)建立索引。因爲在普通數值上的查詢就算使用索引也沒什麼好處,那麼還不如從索引中剔除這些大量重複的行。這樣可以減小索引尺寸,提高那些真正使用索引的查詢的速度。同時它也能提高更新操作的速度,因爲不是所有情況都需要更新索引。
今天在折騰中發現如果對col使用部分索引在ORDER BY col時可能導致全表掃描該字段。pgsql v8.1, 30w條記錄。
1、正常創建索引,order by時使用該索引
CREATE INDEX ftype on table (fee_type);
explain SELECT * FROM test_fee ORDER BY fee_type LIMIT 10
Limit (cost=0.00..0.53 rows=10 width=259)
-> Index Scan using ftype on test_fee (cost=0.00..15882.07 rows=301596 width=259)
Time: 0.015s
explain analyze SELECT * FROM test_fee ORDER BY fee_type LIMIT 10
Limit (cost=0.00..0.53 rows=10 width=259) (actual time=0.049..0.139 rows=10 loops=1)
-> Index Scan using ftype on test_fee (cost=0.00..15881.26 rows=301596 width=259)
(actual time=0.042..0.077 rows=10 loops=1)
Total runtime: 0.263 ms
2、創建部分索引,結果全表掃描
CREATE INDEX ftype ON table (fee_type) WHERE fee_type > 0;
SELECT * FROM test_fee ORDER BY fee_type LIMIT 10
Limit (cost=18217.34..18217.37 rows=10 width=259)
-> Sort (cost=18217.34..18971.33 rows=301596 width=259)
Sort Key: fee_type
-> Seq Scan on test_fee (cost=0.00..11699.96 rows=301596 width=259)
Time: 0.015s
explain analyze SELECT * FROM test_fee ORDER BY fee_type LIMIT 10
Limit (cost=18217.34..18217.37 rows=10 width=259) (actual time=1994.620..1994.701 rows=10 loops=1)
-> Sort (cost=18217.34..18971.33 rows=301596 width=259) (actual time=1994.611..1994.637 rows=10 loops=1)
Sort Key: fee_type
Sort Method: top-N heapsort Memory: 19kB
-> Seq Scan on test_fee (cost=0.00..11699.96 rows=301596 width=259) (actual time=0.060..1022.666 rows=301596 loops=1)
Total runtime: 1994.863 ms
即使fee_type值都大於0(符合部分索引條件),結果一樣。
總結:對使用了部分索引的欄目進行排序時pgsql可能會全表掃描導致性能驟降。除非你在WHERE條件中排除未被索引值的row,比如創建了一個 (fid > 9) 的部分索引,那麼條件爲 “ WHERE fid > 9 ORDER BY fid” 或 “ WHERE fid > 10 ORDER BY fid”就會使用fid上建立的(部分)索引。