2016-08-21 165 views
1

我的應用程序有一個頁面,其中顯示了一個以特定字母開頭的州的所有城市。如何提高ILIKE性能?

對於前:

State: Alabama, Page A 
--> All cities in Alabama starting with alphabet 'A' 

這是我的查詢

City.where(state: 'Alabama').where("name ilike?", "a%") 

此查詢需要〜110 - 140毫秒。有沒有什麼辦法可以將查詢時間降低到012毫秒。

感謝提前:)

+3

你知道['Database_index'(https://en.wikipedia.org/wiki/Database_index)和['PostgreSQL的特性explain'(https://www.postgresql.org/文檔/ 9.4 /靜態/使用-explain.html)? –

+0

@Зелёный城市表在'名稱'列上有一個數據庫索引。我不熟悉'PostgreSQL解釋' – Mahendhar

+0

那麼你應該查找它。鏈接在@Зелёный的評論 – e4c5

回答

3

PostgreSQL沒有使用通常的指數LIKE操作

postgres=# create index on obce(nazev); 
CREATE INDEX 
Time: 120.605 ms 
postgres=# explain analyze select * from obce where nazev like 'P%'; 
┌─────────────────────────────────────────────────────────────────────────────────────────────────────┐ 
│            QUERY  PLAN            │ 
╞═════════════════════════════════════════════════════════════════════════════════════════════════════╡ 
│ Seq Scan on obce (cost=0.00..137.12 rows=435 width=41) (actual time=0.023..2.345 rows=450 loops=1) │ 
│ Filter: ((nazev)::text ~~ 'P%'::text)                │ 
│ Rows Removed by Filter: 5800                  │ 
│ Planning time: 0.485 ms                    │ 
│ Execution time: 2.413 ms                   │ 
└─────────────────────────────────────────────────────────────────────────────────────────────────────┘ 
(5 rows) 

你應該使用特殊的語法與varchar_pattern_ops關鍵字

postgres=# create index on obce(nazev varchar_pattern_ops); 
CREATE INDEX 
Time: 124.709 ms 
postgres=# explain analyze select * from obce where nazev like 'P%'; 
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 
│               QUERY PLAN               │ 
╞═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╡ 
│ Bitmap Heap Scan on obce (cost=12.39..76.39 rows=435 width=41) (actual time=0.291..0.714 rows=450 loops=1)     │ 
│ Filter: ((nazev)::text ~~ 'P%'::text)                      │ 
│ Heap Blocks: exact=58                          │ 
│ -> Bitmap Index Scan on obce_nazev_idx1 (cost=0.00..12.28 rows=400 width=0) (actual time=0.253..0.253 rows=450 loops=1) │ 
│   Index Cond: (((nazev)::text ~>=~ 'P'::text) AND ((nazev)::text ~<~ 'Q'::text))          │ 
│ Planning time: 0.953 ms                          │ 
│ Execution time: 0.831 ms                         │ 
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘ 
(7 rows) 

但是這並未」 t爲ILIKE工作 - 解決方法可以是功能索引:

create index on obce(upper(nazev) varchar_pattern_ops); 
select * from obce where upper(nazev) like upper('P%'); 

注:「Nazev」是

另一種可能性是使用pg_trgm擴展,並使用三元指數捷克語的名字。它同時適用於LIKEILIKE,但索引要大得多 - 對於相對較小的靜態表來說這不是問題。

create extension pg_trgm ; 
create index on obce using gin (nazev gin_trgm_ops); 

postgres=# explain analyze select * from obce where nazev like 'P%'; 
┌─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐ 
│               QUERY PLAN               │ 
╞═════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════════╡ 
│ Bitmap Heap Scan on obce (cost=15.37..79.81 rows=435 width=41) (actual time=0.327..0.933 rows=450 loops=1)     │ 
│ Recheck Cond: ((nazev)::text ~~ 'P%'::text)                    │ 
│ Rows Removed by Index Recheck: 134                      │ 
│ Heap Blocks: exact=58                          │ 
│ -> Bitmap Index Scan on obce_nazev_idx1 (cost=0.00..15.26 rows=435 width=0) (actual time=0.287..0.287 rows=584 loops=1) │ 
│   Index Cond: ((nazev)::text ~~ 'P%'::text)                   │ 
│ Planning time: 0.359 ms                          │ 
│ Execution time: 1.056 ms                         │ 
└─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘  
(8 rows)