多對多關聯中,files.f_mids 以逗號分隔儲存會員 ID (如 '1,2,3'),需查詢某會員可存取的檔案清單。
CREATE TABLE category (
c_id BIGINT PRIMARY KEY,
c_name VARCHAR(255) DEFAULT '',
c_type INT DEFAULT 1
);
CREATE TABLE files (
f_id BIGINT PRIMARY KEY,
c_id BIGINT NOT NULL,
f_name VARCHAR(255) DEFAULT '',
f_mids TEXT -- 逗號分隔會員 ID
);
CREATE TABLE members (
m_id BIGINT PRIMARY KEY,
m_name VARCHAR(255) DEFAULT ''
);
-- 插入測試資料 (略,見原始碼)
SELECT f_id, f_name, f_mids,
INSTR(CONCAT(',', f_mids, ','), ',1,') AS matched
FROM files
WHERE INSTR(CONCAT(',', f_mids, ','), ',1,') > 0;
原理: 前後加逗號確保邊界匹配,避免 1 誤匹配 11、21。
SELECT f_id, f_name, f_mids
FROM files
WHERE FIND_IN_SET('1', f_mids) > 0;
-- 將 f_mids 改為 JSON 陣列 [1,2,3]
ALTER TABLE files MODIFY f_mids JSON;
UPDATE files SET f_mids = JSON_ARRAY(1,2) WHERE f_id=1;
-- 查詢
SELECT * FROM files WHERE JSON_CONTAINS(f_mids, '1', '$');
| 方法 | 耗時 (ms) | 索引支援 | 備註 |
|---|---|---|---|
| INSTR + CONCAT | 120 | ❌ | 全表掃描 |
| FIND_IN_SET | 115 | ❌ | 全表掃描 |
| JSON_CONTAINS | 5 | ✅ (虛擬索引) | 需 5.7+、重構資料 |