【发布时间】:2015-12-07 02:49:02
【问题描述】:
我需要加快这个查询。耗时 12 秒,返回 3917 条记录。我安装的 mySQL 并没有针对性能进行调整,也许我需要修改一些配置变量来帮助提高性能。在查询的大部分时间里,查询都会显示“Copying to tmp table”。
此查询用于生成参数搜索过滤器(即按品牌名称、颜色等过滤搜索结果)。
查询:
SELECT attributenames.attributeid,
search_attribute_values.valueid,
attributenames.name,
search_attribute_values.value,
count(search_attribute_values.value) as count,
search_attribute_values.absolutevalue
FROM product
INNER JOIN vendorimport
ON (vendorimport.productid = product.productid
AND product.categoryid = 4871)
INNER JOIN search_attribute
ON (search_attribute.productid = product.productid
AND search_attribute.localeid = 1)
INNER JOIN search_attribute_values
ON (search_attribute.valueid = search_attribute_values.valueid)
INNER JOIN attributenames
ON (attributenames.attributeid = search_attribute.attributeid
AND attributenames.localeid = 1)
GROUP BY attributenames.attributeid, search_attribute_values.valueid
解释:
+----+-------------+-------------------------+--------+----------------------------------------------------+----------------------------+---------+---------------------------------------+-------+----------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------------------------+--------+----------------------------------------------------+----------------------------+---------+---------------------------------------+-------+----------------------------------------------+
| 1 | SIMPLE | product | ref | PRIMARY,product_categoryID,categoryid_productid | categoryid_productid | 4 | const | 38729 | Using index; Using temporary; Using filesort |
| 1 | SIMPLE | vendorimport | ref | productimport_productid | productimport_productid | 5 | microcad.product.productid | 1 | Using where; Using index |
| 1 | SIMPLE | search_attribute | ref | PRIMARY | PRIMARY | 8 | microcad.vendorimport.productid,const | 8 | Using where; Using index |
| 1 | SIMPLE | attributenames | ref | attributenames_attributeID,attributenames_localeID | attributenames_attributeID | 8 | microcad.search_attribute.attributeid | 4 | Using where |
| 1 | SIMPLE | search_attribute_values | eq_ref | PRIMARY | PRIMARY | 4 | microcad.search_attribute.valueid | 1 | |
+----+-------------+-------------------------+--------+----------------------------------------------------+----------------------------+---------+---------------------------------------+-------+----------------------------------------------+
架构:
--
-- Table structure for table `attributenames`
--
DROP TABLE IF EXISTS `attributenames`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `attributenames` (
`attributeid` bigint(20) NOT NULL DEFAULT '0',
`name` varchar(110) NOT NULL DEFAULT '',
`localeid` int(11) NOT NULL DEFAULT '0',
KEY `attributenames_attributeID` (`attributeid`),
KEY `attributenames_localeID` (`localeid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `product`
--
DROP TABLE IF EXISTS `product`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `product` (
`productid` int(11) NOT NULL DEFAULT '0',
`manufacturerid` int(11) NOT NULL DEFAULT '0',
`isactive` tinyint(1) NOT NULL DEFAULT '1',
`mfgpartno` varchar(70) NOT NULL DEFAULT '',
`categoryid` int(11) NOT NULL DEFAULT '0',
`isaccessory` tinyint(1) NOT NULL DEFAULT '0',
`equivalency` double NOT NULL DEFAULT '0',
`creationdate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00',
`modifieddate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`lastupdated` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
PRIMARY KEY (`productid`),
KEY `product_manufacturerID` (`manufacturerid`),
KEY `product_categoryID` (`categoryid`),
KEY `product_mfgPartNo` (`mfgpartno`),
KEY `categoryid_productid` (`categoryid_productid`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `search_attribute`
--
DROP TABLE IF EXISTS `search_attribute`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `search_attribute` (
`productid` int(11) NOT NULL DEFAULT '0',
`attributeid` bigint(20) NOT NULL DEFAULT '0',
`valueid` int(11) NOT NULL DEFAULT '0',
`localeid` int(11) NOT NULL DEFAULT '0',
`setnumber` tinyint(2) NOT NULL DEFAULT '0',
`isactive` tinyint(1) NOT NULL DEFAULT '1',
PRIMARY KEY (`productid`,`localeid`,`attributeid`,`setnumber`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
--
-- Table structure for table `search_attribute_values`
--
DROP TABLE IF EXISTS `search_attribute_values`;
/*!40101 SET @saved_cs_client = @@character_set_client */;
/*!40101 SET character_set_client = utf8 */;
CREATE TABLE `search_attribute_values` (
`valueid` int(11) NOT NULL DEFAULT '0',
`value` varchar(255) NOT NULL DEFAULT '',
`absolutevalue` double NOT NULL DEFAULT '0',
`unitid` int(11) NOT NULL DEFAULT '0',
`isabsolute` tinyint(1) NOT NULL DEFAULT '0',
PRIMARY KEY (`valueid`),
KEY `search_attrval_value` (`value`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;
/*!40101 SET character_set_client = @saved_cs_client */;
每张表的记录数:
search_attribute 为 72,000,000, search_attribute_values 是 350,000, 产品为 4,000,000
【问题讨论】:
-
首先,我建议您摆脱默认值(尤其是在 varchar 列上)并使用 NULL。此外,您应该阅读索引(集群和非集群)并考虑在查询中经常引用的列上使用它们。最后,查看查询的查询计划,看看瓶颈在哪里。
-
我已将 varchar 列的默认值更改为 NULL。我已经在我经常使用的列上有很多索引。我有兴趣加快这个特定的查询。
-
我将首先在
category_id, product_id上创建一个索引,然后运行一个简单的查询select product_id from product where category_id = 4871。这是您的查询将运行的最快速度。然后从那里构建。 -
@JRD 我将 (categoryid,productid) 的索引添加到产品表中,现在解释显示“使用索引”,我已经更新了原始问题以显示它。查询仍然较慢。
-
再次查看查询,您 GROUP BY 来自 2 个不同表的 attributeid 和 valueid,但它们的值都在 search_attribute 表上。如果您切换到从 search_attribute 获取值,并对来自 search_attribute 的值进行分组,那么它可能会利用 search_attribute 表上这些字段的索引。
标签: mysql performance optimization