我的 MySQL 数据库有一个查询,用于在用户在自由格式文本框中执行搜索后返回产品(在电子商务网站上)。
直到最近,用户搜索一直在快速运行。然而,在过去的几天里,搜索速度有时会非常缓慢。这种情况每天发生大约 3 或 4 小时(全天随机分布)。
我以为我的服务器有问题。但现在我已经转移到另一台服务器了,同样的事情仍然发生。
我怀疑我使用的查询效率很低,也许这就是原因。但我不明白为什么通常查询可以运行得很快,而有时却很慢。我认为低效的查询总是很慢。
查询在两个表上运行。如果搜索“blue jeans”,那么查询将如下所示:
SELECT I.itemURL, I.itemTitle, I.itemPrice, I.itemReduced, I.itemFileName, I.itemBrand, I.itemStore, I.itemID, I.itemColour, I.itemSizes, I.itemBrandEn
FROM Item AS I, Search AS S
WHERE I.itemID = S.itemID
AND (S.searchStringTEXT LIKE '% blue %' OR S.searchStringTEXT LIKE 'blue %' OR S.searchStringTEXT LIKE '% blue')
AND (S.searchStringTEXT LIKE '% jeans %' OR S.searchStringTEXT LIKE 'jeans %' OR S.searchStringTEXT LIKE '% jeans')
Item 是包含网站上所有产品的表。它有大约 100,000 行。
搜索是一个包含产品 ID 以及与每个产品 ID 关联的标签的表。标签位于“searchStringTEXT”列中,并以空格分隔。例如,此列中的条目可能类似于“Jeans Blue Calvin Klein Small”。
上面的搜索将找到所有同时带有“jeans”和“blue”标签的商品。
理论上,Search 应该与 Item 具有相同的行数;但是,由于我尚未修复的问题,它的行数减少了大约 500 行,因此这些项目实际上已从搜索中排除。
两个表的创建表详细信息如下:
CREATE TABLE `Search` (
`itemID` int(11) NOT NULL,
`searchStringTEXT` varchar(255) DEFAULT NULL,
`searchStringVARCHAR` varchar(1000) DEFAULT NULL,
PRIMARY KEY (`itemID`),
KEY `indexSearch_837` (`itemID`) USING BTREE,
KEY `indexSearch_837_text` (`searchStringTEXT`)
) ENGINE=InnoDB DEFAULT CHARSET=latin5
和
CREATE TABLE `Item_8372` (
`itemID` int(11) NOT NULL AUTO_INCREMENT,
`itemURL` varchar(2000) DEFAULT NULL,
`itemTitle` varchar(500) DEFAULT NULL,
`itemFileName` varchar(200) DEFAULT NULL,
`itemPictureURL` varchar(2000) DEFAULT NULL,
`itemReduced` int(11) DEFAULT NULL,
`itemPrice` int(11) DEFAULT NULL,
`itemStore` varchar(500) DEFAULT NULL,
`itemBrand` varchar(500) CHARACTER SET latin1 DEFAULT NULL,
`itemShopCat` varchar(500) DEFAULT NULL,
`itemTimestamp` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`itemCat` varchar(200) DEFAULT NULL,
`itemSubCat` varchar(200) DEFAULT NULL,
`itemSubSubCat` varchar(200) DEFAULT NULL,
`itemSubSubSubCat` varchar(200) DEFAULT NULL,
`itemColour` varchar(200) DEFAULT NULL,
`itemSizes` varchar(200) DEFAULT NULL,
`itemBrandEn` varchar(500) DEFAULT NULL,
`itemReduction` float DEFAULT NULL,
`ItemPopularity` int(6) DEFAULT NULL,
PRIMARY KEY (`itemID`),
KEY `indexItem_8372_ts` (`itemTimestamp`) USING BTREE,
KEY `indexItem_8372_pop` (`ItemPopularity`),
KEY `indexItem_8372_red` (`itemReduction`),
KEY `indexItem_8372_price` (`itemReduced`)
) ENGINE=InnoDB AUTO_INCREMENT=970846 DEFAULT CHARSET=latin5
在问题的标题中我说“(在我的网站上运行时)”,因为我发现查询的速度在本地运行时是一致的。但也许这只是因为我没有在本地测试过太多。
我正在考虑更改搜索表,使其成为 MyISAM 表,然后我可以使用全文搜索而不是“LIKE”。但我仍然想弄清楚为什么我会遇到当前设置所遇到的情况。
非常感谢任何想法/建议, 安德鲁
编辑:
以下是 SELECT 语句的 EXPLAIN 结果:
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE I ALL PRIMARY NULL NULL NULL 81558
1 SIMPLE S eq_ref PRIMARY,indexSearch_837,indexSearch_837_text PRIMARY 4 I.itemID 1 Using where
最佳答案
使用LIKE
会导致查询速度变慢,尤其是使用它的次数。这是因为 LIKE
会扫描表中的所有行,即使有几百行也可能会导致问题(再加上您使用不同变体的 LIKE
的次数)要匹配的文本)。
只需要几个人同时加载运行此查询的页面即可真正减慢您的网站速度。此外,该查询可能会在服务器上的后台线程中多次运行,从而导致您看到的长期速度下降。
如果您要定期执行文本搜索,请考虑使用基于 RAM 的搜索索引解决方案,例如 Sphinx。您可以在那里执行文本搜索(与 MySQL 相比,它会非常快),然后从 MySQL 表中检索所需的行。
关于MySQL 查询通常很快,有时很慢(在我的网站上运行时),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13824222/