3

我在PostgreSQL 9.3數據庫中有3億個地址,我想用pg_trgm來模糊搜索行。最終目的是像谷歌地圖搜索一樣實施搜索功能。在3億個地址中搜索pg_trgm

當我使用pg_trgm搜索這些地址時,花費大約30秒才能得到結果。有很多行匹配0.3的默認相似性閾值條件,但我只需要大約5或10個結果。我創建了一個卦的GiST索引:

CREATE INDEX addresses_trgm_index ON addresses USING gist (address gist_trgm_ops); 

這是我的查詢:

SELECT address, similarity(address, '981 maun st') AS sml 
FROM addresses 
WHERE address % '981 maun st' 
ORDER BY sml DESC 
LIMIT 10; 

對生產環境的測試表已被刪除。我顯示了我測試環境下的EXPLAIN輸出。大約有700萬行,需要大約1.6秒才能得到結果。有3億,需要30多個。

ebdb=> explain analyse select address, similarity(address, '781 maun st') as sml from addresses where address % '781 maun st' order by sml desc limit 10; 
            QUERY PLAN                    
————————————————————————————————————————————————————————————————————————————————  
Limit (cost=7615.83..7615.86 rows=10 width=16) (actual time=1661.004..1661.010 rows=10 loops=1) 
-> Sort (cost=7615.83..7634.00 rows=7268 width=16) (actual time=1661.003..1661.005 rows=10 loops=1) 
    Sort Key: (similarity((address)::text, '781 maun st'::text)) 
    Sort Method: top-N heapsort Memory: 25kB 
    -> Index Scan using addresses_trgm_index on addresses (cost=0.41..7458.78 rows=7268 width=16) (actual time=0.659..1656.386 rows=5241 loops=1) 
      Index Cond: ((address)::text % '781 maun st'::text) 
Total runtime: 1661.066 ms 
(7 rows) 

有沒有一種很好的方法來提高性能,或者它是一個很好的計劃做表分區?

+1

「...我只需要大約5或10個結果」...你是否在查詢中放置了一個合適的LIMIT? –

+0

分區在Postgres 9.3中可用,但是使用表繼承來實現。它在postgres 10中明確提供。 – Mokadillion

+0

我認爲「300MM +」意味着3億?如果是這樣,你應該考慮使用ElasticSearch或類似的東西。 –

回答

1

PostgreSQL 9.3 ...有沒有一種很好的方法來提高性能或是一個很好的計劃做表分區?

表分區將不會幫助根本沒有

但是,有一個好方法:升級到當前版本的Postgres。 GiST索引有很多改進,特別是pg_trgm模塊和一般的大數據。 Postgres 9.6或即將推出的Postgres 10(目前測試版)應該大大提高速度。

你「近鄰」看起來是正確的,但對於小LIMIT使用該等效查詢,而不是:

SELECT address, similarity(address, '981 maun st') AS sml 
FROM addresses 
WHERE address % '981 maun st' 
ORDER BY address <-> '981 maun st' 
LIMIT 10;

Quoting the manual:

它通常會打第一製劑時,只有少數的 最接近的比賽是想要的。