Index-Tuning
用於未錨定 LIKE 條件的良好數據庫
基本上我需要一個能夠很好地處理諸如
LIKE %abc%
.我已經嘗試過使用 GIN 索引的 PostgreSQL,它非常好,但也許有更好的東西?我也試過 MongoDB,發現像“/abc/”這樣的查詢效果很差,而且 Mongo 索引只支持“/^abc/”。
我的數據庫結構很簡單。
PostgreSQL 中的範例查詢:
SELECT DISTINCT(id), title FROM data AS data INNER JOIN datatosynonym AS dts ON dts.data_id = data.id WHERE dts.synonym_simple LIKE "%abc%"
在MongoDB 中
db.data.find({synonymssimple: /abc/})
其中 synonymssimple 是一個字元串數組。
PostgreSQL 中的範例數據
數據表:
id | title | timestamp 1 | Abc | 1145836800 2 | Qwe | 1145836800
數據同義詞表:
id | synonym_simple | data_id 1 | abc | 1 2 | bac | 1
我的基準測試顯示以下結果:
- 具有 b-tree 索引和 %abc% 查詢的 PostgreSQL - 每個查詢約 15 毫秒
- 具有 b-tree 索引和 abc% 查詢的 PostgreSQL - 每個查詢約 1 毫秒
- 具有 GIN 索引和 %abc% 查詢的 PostgreSQL - 每個查詢約 1.5 毫秒
- 具有 GIN 索引和 abc% 查詢的 PostgreSQL - 每個查詢約 1 毫秒
- 沒有索引和 /abc/ 查詢的 MongoDB - 每個查詢約 25 毫秒
- 具有 b-tree 索引和 /abc/ 查詢的 MongoDB - 每個查詢約 80 毫秒
- 具有 b-tree 索引和 /^abc/ 查詢的 MongoDB - 每個查詢約 0.25 毫秒
遺憾的是我不能使用 /^abc/ 查詢。
一種技術是將“未錨定”查詢分成兩個“錨定”部分。
正如您所展示的,帶有尾隨萬用字元的 B-Tree 搜尋速度很快。問題是您還需要一個前導萬用字元。如果您可以將前導萬用字元變成尾隨萬用字元,那就太好了。REVERSE功能在這裡會有所幫助。查詢變為
WHERE dts.synonym_simple LIKE "abc%" AND dts.synonym_simple_reversed LIKE "cba%"
為了有效,必須在反轉文本上有一個索引。這是寫入時的成本,將使用額外的儲存空間。等到讀取時間將需要掃描數據,這反而違背了目的。請參閱此處的範例。