我有一個數據庫中的表像這樣 關鍵詞有效的搜索查詢
- ID INT(11)
- U_ID INT(11)
- 關鍵字文本
- CREATE_DATE INT的結構( 11)
U_ID爲外鍵,id是主鍵
關鍵字字段是用戶創建的用逗號分隔的單詞列表 我想知道是否有人可以建議有效的查詢來搜索這樣的表。
我有一個數據庫中的表像這樣 關鍵詞有效的搜索查詢
U_ID爲外鍵,id是主鍵
關鍵字字段是用戶創建的用逗號分隔的單詞列表 我想知道是否有人可以建議有效的查詢來搜索這樣的表。
如果使用MyISAM,則可以在字段keywords
上創建全文索引。然後搜索使用:
select * from keywords k where match('test') against(k.keywords);
當然,在數據庫中的CSV只是你可以做的最糟糕的事情。你應該把關鍵字放在一個單獨的表格中。確保對所有表使用InnoDB。
Table tags
-------------
id integer auto_increment primary key
keyword_id integer foreign key references keywords(id)
keyword varchar(40)
現在您可以選擇使用:
SELECT k.* FROM keywords k
INNER JOIN tags t ON (t.keyword_id = k.id)
WHERE t.keyword LIKE 'test' //case insensitive comparison.
比CSV很多快得多。
謝謝,我認爲這將簡化事情 – MrFoh
您應該更改數據庫設計,以便擁有一個名爲user_keyword
的表並將每個關鍵字存儲在單獨的行中。然後,您可以索引此表並輕鬆地和有效地搜索它:
WHERE keyword = 'foo'
如果不能修改數據庫那麼你可以使用FIND_IN_SET
但它不會是非常有效:
WHERE FIND_IN_SET('foo', keywords)
你有2種選擇:
SELECT * FROM Keywords WHERE keyword LIKE %KEYWORD%
錯誤的答案,在一個帶有「book,testing」的CSV列中,即使'test'本身不在該列中,這也會給出匹配。在SQL和php中混合查詢本身就是一種反模式。 – Johan
單獨的keywords
在它自己的表中,通過FOREIGN KEY將它連接到舊錶,將它索引,並且您將能夠有效地搜索關鍵字前綴的確切關鍵字。
例如:
id U_id keywords create_date
1 - A,B,C -
變爲:
PARENT_TABLE:
id U_id create_date
1 - -
CHILD_TABLE:
id keyword
1 A
1 B
1 C
提供有上keyword
索引,以下查詢應該是有效的:
SELECT * FROM PARENT_TABLE
WHERE id IN (SELECT id FROM CHILD_TABLE WHERE keyword = ...)
--- EDIT ---
根據Johan的下面的評論,似乎InnoDB在大多數其他數據庫下使用Oracle或「集羣」下的「索引組織表」。假設您不需要查詢「從父母到孩子」(即,「給我定的ID的所有關鍵字」),對CHILD_TABLE的PRIMARY KEY應該是:
{keyword, id}
由於keyword
是複合索引中的第一個字段,WHERE keyword = ...
(或WHERE keyword LIKE 'prefix%'
)可以直接使用該索引。
沒有自己的PK的innoDB表將表現得很差。 – Johan
@Johan OK,我忘了提及這一點,但CHILD_TABLE的主鍵是:{id,keyword}。 –
@Johan順便說一句,爲什麼它表現不佳(我不是MySQL/innoDB專家)? –
切勿在數據庫中使用CSV。這是一個主要的罪惡! – Johan