我在我的MySQL数据库上有一个查询,用于在用户在自由格式文本框中执行搜索后返回产品(在电子商务网站上)。
直到最近,用户搜索一直在快速运行。但是,在过去的几天里,搜索定期非常缓慢。这种情况每天发生约3或4小时(在一天中随机散布)。
我原以为我的服务器出了问题。但现在我已经转移到另一台服务器,同样的事情仍然发生。
我怀疑我使用的查询是非常低效的,也许这就是原因。但我不明白为什么通常查询可以快速运行,而在其他时候非常慢。我认为低效的查询总是很慢。
查询在两个表上运行。如果搜索的是“蓝色牛仔裤”,那么查询将如下所示:
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')
项目是包含网站上所有产品的表格。它有大约100,000行。
搜索是一个包含产品ID的表格,以及与每个产品ID相关联的标签。标签位于“searchStringTEXT”列中,并以空格分隔。例如,本栏目中的条目可能类似于“牛仔裤蓝色卡尔文克莱因小”。
上面的搜索将找到所有标有“牛仔裤”和“蓝色”标签的物品。
理论上,Search应该与Item具有相同的行数;但是,由于我还没有解决的问题,它的行数减少了约500,所以这些项目实际上被排除在搜索范围之外。
两个表的create table详细信息如下:
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
答案 0 :(得分:1)
使用LIKE
会导致查询速度变慢,尤其是您拥有它的次数。这是因为LIKE
会扫描表格中的所有行,即使只有几百行也会导致出现问题(添加使用LIKE
的次数与文本的不同变体相匹配)
只需要几个人同时加载运行此查询的网页即可真正降低网站速度。此外,查询可能在您的服务器上以前面的后台线程运行多次,导致您看到的长期减速。
如果您要定期执行文本搜索,请考虑使用基于RAM的索引搜索解决方案,例如Sphinx。您可以在那里执行文本搜索(与MySQL相比速度非常快),然后从MySQL表中检索所需的行。
答案 1 :(得分:1)
您可能想尝试使用REGEXP
(reference)。停止使用隐式连接也是一种更好的做法。
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
INNER JOIN search AS S
ON I.itemid = S.itemid
WHERE S.searchstringtext REGEXP ' blue | blue|blue '
AND S.searchstringtext REGEXP ' jeans | jeans|jeans '