0

我在我的 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”列中,并用空格分隔。例如,此列中的条目可能类似于“牛仔裤蓝色 calvin klein small”。

上面的搜索将找到所有带有标签“牛仔裤”和“蓝色”的商品。

理论上,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
4

2 回答 2

1

使用LIKE会导致查询缓慢,尤其是您拥有它的次数。这是因为LIKE扫描表中的所有行,即使有几百行也会导致问题(再加上您使用LIKE不同文本变体匹配的次数)。

只需要几个人同时加载运行此查询的页面即可真正减慢您的网站速度。此外,查询可能会在您的服务器上以较早的后台线程运行多次,从而导致您看到的长期减速。

如果您要定期执行文本搜索,请考虑为您的搜索使用基于 RAM 的索引解决方案,例如 Sphinx。您可以在那里执行文本搜索(与 MySQL 相比它将非常快),然后从 MySQL 表中检索所需的行。

于 2012-12-11T16:29:23.533 回答
1

您可能想尝试使用REGEXP参考)。停止使用隐式连接也是更好的做法。

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 ' 
于 2012-12-11T16:46:26.197 回答