Index-Tuning

用於未錨定 LIKE 條件的良好數據庫

  • August 3, 2017

基本上我需要一個能夠很好地處理諸如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

我的基準測試顯示以下結果:

  1. 具有 b-tree 索引和 %abc% 查詢的 PostgreSQL - 每個查詢約 15 毫秒
  2. 具有 b-tree 索引和 abc% 查詢的 PostgreSQL - 每個查詢約 1 毫秒
  3. 具有 GIN 索引和 %abc% 查詢的 PostgreSQL - 每個查詢約 1.5 毫秒
  4. 具有 GIN 索引和 abc% 查詢的 PostgreSQL - 每個查詢約 1 毫秒
  5. 沒有索引和 /abc/ 查詢的 MongoDB - 每個查詢約 25 毫秒
  6. 具有 b-tree 索引和 /abc/ 查詢的 MongoDB - 每個查詢約 80 毫秒
  7. 具有 b-tree 索引和 /^abc/ 查詢的 MongoDB - 每個查詢約 0.25 毫秒

遺憾的是我不能使用 /^abc/ 查詢。

一種技術是將“未錨定”查詢分成兩個“錨定”部分。

正如您所展示的,帶有尾隨萬用字元的 B-Tree 搜尋速度很快。問題是您還需要一個前導萬用字元。如果您可以將前導萬用字元變成尾隨萬用字元,那就太好了。REVERSE功能在這裡會有所幫助。查詢變為

WHERE dts.synonym_simple LIKE "abc%"
AND dts.synonym_simple_reversed LIKE "cba%"

為了有效,必須在反轉文本上有一個索引。這是寫入時的成本,將使用額外的儲存空間。等到讀取時間將需要掃描數據,這反而違背了目的。請參閱此處的範例。

引用自:https://dba.stackexchange.com/questions/176224