Magento慢类别计数查询

问题描述 投票:0回答:1

我们最近在Magento商店中部署了一些更改,这些更改已触发以下SQL运行:

SELECT `count_table`.`category_id`, COUNT(DISTINCT count_table.product_id) AS `product_count` 

FROM `catalog_product_flat_1` AS `e`

INNER JOIN `catalog_category_product_index` AS `cat_index` ON cat_index.product_id=e.entity_id AND cat_index.store_id=1 AND cat_index.visibility IN(2, 4) AND 1

INNER JOIN `catalog_product_index_price` AS `price_index` ON price_index.entity_id = e.entity_id AND price_index.website_id = '1' AND price_index.customer_group_id = 0

INNER JOIN `catalog_product_index_eav` AS `brand_idx` ON brand_idx.entity_id = e.entity_id AND brand_idx.attribute_id = '135' AND brand_idx.store_id = 1 AND brand_idx.value IN('967')

INNER JOIN `catalog_product_flat_1` ON catalog_product_flat_1.entity_id=e.entity_id

INNER JOIN `catalog_product_flat_1` AS `catalog_product_flat_1_2` ON catalog_product_flat_1.entity_id=e.entity_id

INNER JOIN `catalog_category_product_index` AS `count_table` ON count_table.product_id = e.entity_id 

WHERE (e.status = 1) AND (catalog_product_flat_1.brand = '967') AND (catalog_product_flat_1.brand = '967') AND (count_table.store_id = 1) AND (count_table.category_id IN ('335', '334', '332', '339', '337', '943')) 

GROUP BY `count_table`.`category_id`;

此SQL需要几秒钟才能运行,如果有多个用户同时访问同一页面,服务器最终会在查询备份时停止运行。

运行EXPLAIN提供了这个:

1   SIMPLE  brand_idx   ref PRIMARY,IDX_CATALOG_PRODUCT_INDEX_EAV_ENTITY_ID,IDX_CATALOG_PRODUCT_INDEX_EAV_ATTRIBUTE_ID,IDX_CATALOG_PRODUCT_INDEX_EAV_STORE_ID,IDX_CATALOG_PRODUCT_INDEX_EAV_VALUE   IDX_CATALOG_PRODUCT_INDEX_EAV_VALUE 4   const   17  Using where; Using index; Using temporary; Using filesort
1   SIMPLE  count_table ref PRIMARY,IDX_CAT_CTGR_PRD_IDX_PRD_ID_STORE_ID_CTGR_ID_VISIBILITY,15D3C269665C74C2219037D534F4B0DC    IDX_CAT_CTGR_PRD_IDX_PRD_ID_STORE_ID_CTGR_ID_VISIBILITY 6   db.brand_idx.entity_id,const    1   Using where; Using index
1   SIMPLE  e   eq_ref  PRIMARY,IDX_CATALOG_PRODUCT_FLAT_1_STATUS   PRIMARY 4   db.brand_idx.entity_id  1   Using where
1   SIMPLE  cat_index   ref IDX_CAT_CTGR_PRD_IDX_PRD_ID_STORE_ID_CTGR_ID_VISIBILITY,15D3C269665C74C2219037D534F4B0DC    IDX_CAT_CTGR_PRD_IDX_PRD_ID_STORE_ID_CTGR_ID_VISIBILITY 6   db.brand_idx.entity_id,const    1   Using where; Using index
1   SIMPLE  catalog_product_flat_1  eq_ref  PRIMARY PRIMARY 4   db.brand_idx.entity_id  1   Using where
1   SIMPLE  price_index eq_ref  PRIMARY,IDX_CATALOG_PRODUCT_INDEX_PRICE_CUSTOMER_GROUP_ID,IDX_CATALOG_PRODUCT_INDEX_PRICE_WEBSITE_ID,IDX_CAT_PRD_IDX_PRICE_WS_ID_CSTR_GROUP_ID_MIN_PRICE    PRIMARY 8   db.brand_idx.entity_id,const,const  1   Using index
1   SIMPLE  catalog_product_flat_1_2    index   NULL    IDX_CATALOG_PRODUCT_FLAT_1_ATTRIBUTE_SET_ID 2   NULL    21529   Using index; Using join buffer (flat, BNL join)

根据使用brand_idxUsing temporary; Using filesort表,对我而言,这表明某处缺少索引。但这是真的吗?

如果是,我如何识别缺失的索引,其次,如何在Magento中应用此索引?

我知道这也与选择COUNT(DISTINCT count_table.product_id)count_table.category_id分组有关,因为删除这些部分中的任何一个都会导致更快的查询(只是没有预期的信息!)。

mysql sql magento magento-1.9 query-performance
1个回答
0
投票

这个问题是引用同一个表inner join的两个catalog_product_flat_1的结果,但是第二个连接实例的连接条件引用了第一个表:

INNER JOIN `catalog_product_flat_1` ON catalog_product_flat_1.entity_id=e.entity_id

INNER JOIN `catalog_product_flat_1` AS `catalog_product_flat_1_2` ON **catalog_product_flat_1**.entity_id=e.entity_id

虽然问题引用了Magento,但这实际上与Zend_Db以及定义连接的方式有关。

给定Zend_Db_Select对象,您可以创建一个连接,如下所示:

$select->joinInner('catalog_product_flat_1', 'catalog_product_flat_1.entity_id = e.entity_id');

这是第一次你这样做,但如果你第二次这样做,joinInner函数将智能地识别catalog_product_flat_1表上的第二个连接并称之为catalog_product_flat_1_2,但问题出现是因为它没有识别错误连接条件中的表别名。

解决此问题的方法是通过提供名称关联来显式设置表别名,如下所示:

$select->joinInner(array('unique_table_alias' => 'catalog_product_flat_1'), 'unique_table_alias.entity_id = e.entity_id');

在第二个连接引用正确的表别名时,查询时间从3s减少到20ms

Magento两次添加内部联接的事实是另一回事,但一旦配置正确,不会影响性能。

© www.soinside.com 2019 - 2024. All rights reserved.