MySQL - FIND_IN_SET

MySQL:8.0.26

MySQL 中的 FIND_IN_SET 函式是用來搜尋與 StringList 符合的字串。

用法上為:FIND_IN_SET(str, strList)

Basic Usage

先假設一個情境,假設資料庫中有數本書的資料,每本都帶有不同且多個 分類(Category),而分類是透過 StringList 表示。

name    category
Book1   1,2,3
Book2   1,3
Book3   1,8,10
Book4   2,9
Book5   1,9,11
Book6   9,25
Book7   9,12

如果要找出有 9 這個分類的書本,可以直接在 query 中使用 FIND_IN_SET 這個函式。

SELECT * FROM `table` WHERE FIND_IN_SET('9', category);

Performance issue

不過,使用 FIND_IN_SET 時並不會利用到 Index,因此每次的操作其實都是 Full table scan,在資料量很大的時候就會有很嚴重的效能問題。

要解決這個問題可以透過降低資料分母的概念去調整:

Step 1. 先找出 table 中不重複的 category(降低分母)
SELECT DISTINCT category FROM table;
Step 2. 透過 sub query 針對第一步的結果做 FIND_IN_SET(確認結果)
SELECT * FROM (SELECT DISTINCT category FROM table) as T WHERE FIND_IN_SET('9', T.category);
Step 3. 再用確認的結果去搜尋(使用 Index)
SELECT * FROM table WHERE `category` IN ('1,9,11', '2,9', '9,12', '9,25');
Categories: MySQL