我正在尝试优化用于从数据库中的字段进行自动完成的查询。我目前的尝试是使用like
和外卡,但即使我添加了索引,查询也需要很长时间。
CREATE TABLE IF NOT EXISTS `pharma` (
`ID` int(4) NOT NULL,
`drug` varchar(90) DEFAULT NULL, //index
`form` varchar(20) DEFAULT NULL,
`price` decimal(7,2) DEFAULT NULL,
`Company` varchar(54) DEFAULT NULL,
`Pharmacology` varchar(96) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=92064 ;
SELECT *
FROM `pharma`
WHERE `drug` LIKE '%PANADOL%' ESCAPE '!'
AND `drug` LIKE '%500%' ESCAPE '!'
AND `drug` LIKE '%mg%' ESCAPE '!'
AND `drug` LIKE '%fc%' ESCAPE '!'
AND `drug` LIKE '%PANADOL%' ESCAPE '!'
AND `drug` LIKE '%500%' ESCAPE '!'
AND `drug` LIKE '%mg%' ESCAPE '!'
ORDER BY (CASE
when drug LIKE 'PANADOL %' then 1
when drug LIKE 'PANADOL%' then 2
when drug LIKE '% PANADOL%' then 3
when drug LIKE '%PANADOL%' then 4
else 4
end)
LIMIT 15; //average excution time 1.7sec;
我尝试将表格转换为MYISAM
以使用fulltext
索引,但我无法对其进行调整以充当有效搜索。因为我的用户通常输入与数据库中的记录顺序不同的单词,所以我需要使用导致索引无用的前导%
。
答案 0 :(得分:0)
MATCH (drug) AGAINST ('+PANADOL +500 +mg' IN BOOLEAN MODE)
然而,在将ft_min_word_len更改为2之后,您必须[重新]构建索引才能捕获" mg"。
使用" +"和" BOOLEAN",这些单词的顺序无关紧要。但是," 500mg"不会被抓住,所以你应该把它分成" 500毫克"插入时。
当桌子很大时,使用LIKE和%的速度非常慢。特别是因为你有多个LIKE。
一种折衷方法是使用FULLTEXT查找某些单词,然后使用LIKE确保它们正确传播。 FT将会很快并且提供的行数要少得多。例如:
SELECT ... FROM tbl
WHERE MATCH(drug) AGAINST('+PANADOL' IN BOOLEAN MODE)
AND ... LIKE ...
AND ... LIKE ...
...
ORDER BY ...;
此外,它可能值得预先形成上述查询,但它返回空,然后假设PANADOL丢失并对其余单词执行较慢的LIKE。这样,大多数查询都可以快速查询,同时惩罚那些无法正确拼写药物的人。