我们最近将Magento应用程序从私有主机迁移到AWS web服务。我们注意到Magento的一些内部功能在迁移之后执行时间过长,因此开始研究。
其中一个查询是一个简单的客户选择查询,大约有9-10个常规联接到属性表以获取属性。
我们在查询上运行了一些测试,发现旧主机和AWS之间的区别是,在旧主机上,MySQL优化器似乎使用正确的索引,而在AWS中,它使用文件短而忽略索引。
FORCE INDEX(index_name)使查询在AWS中正确执行,但是我们不想沿着这条路走下去,我们宁愿修复数据库配置中的问题,也不愿使用在我们的Magento应用程序中使用手动黑客。为了清楚,我们索引的一个问题,它们的设置是正确的。
背景:
FORCE INDEX()强制RDS以与旧主机相同的方式运行时。旧的MySQL服务器正在运行版本5.1.61,我们正在运行的AWS实例位于5.6.19上。一个咨询小组建议我们将RDS实例降级到5.1.61,但是我们不想这样做,因为这不是一个可持续的解决方案。
所讨论的查询如下(为空间起见,从select中删除字段可缩短):
SELECT
`e`.*
-- various field names here, removed
FROM `customer_entity` AS `e`
LEFT JOIN `customer_entity_int` AS `at_default_billing` ON (`at_default_billing`.`entity_id` = `e`.`entity_id`) AND (`at_default_billing`.`attribute_id` = '13')
LEFT JOIN `customer_address_entity_varchar` AS `at_billing_postcode` ON (`at_billing_postcode`.`entity_id` = `at_default_billing`.`value`) AND (`at_billing_postcode`.`attribute_id` = '30')
LEFT JOIN `customer_address_entity_varchar` AS `at_billing_city` ON (`at_billing_city`.`entity_id` = `at_default_billing`.`value`) AND (`at_billing_city`.`attribute_id` = '26')
LEFT JOIN `customer_address_entity_varchar` AS `at_billing_telephone` ON (`at_billing_telephone`.`entity_id` = `at_default_billing`.`value`) AND (`at_billing_telephone`.`attribute_id` = '31')
LEFT JOIN `customer_address_entity_varchar` AS `at_billing_regione` ON (`at_billing_regione`.`entity_id` = `at_default_billing`.`value`) AND (`at_billing_regione`.`attribute_id` = '28')
LEFT JOIN `customer_address_entity_varchar` AS `at_billing_country_id` ON (`at_billing_country_id`.`entity_id` = `at_default_billing`.`value`) AND (`at_billing_country_id`.`attribute_id` = '27')
LEFT JOIN `core_store` AS `at_store_name` ON (at_store_name.`store_id`=e.store_id)
LEFT JOIN `customer_entity_varchar` AS `firstname` ON e.entity_id = firstname.entity_id AND firstname.attribute_id = 5
LEFT JOIN `customer_entity_varchar` AS `lastname` ON e.entity_id = lastname.entity_id AND lastname.attribute_id = 7
WHERE (`e`.`entity_type_id` = '1')
ORDER BY `e`.`entity_id`
DESC LIMIT 20;当EXPLAIN处理此查询时,服务器之间的差异摘要如下:
RDS - MySQL v5.6.19:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: e
type: ref
possible_keys: IDX_CUSTOMER_ENTITY_ENTITY_TYPE_ID
key: IDX_CUSTOMER_ENTITY_ENTITY_TYPE_ID
key_len: 2
ref: const
rows: 653990
Extra: Using temporary; Using filesort旧主机- MySQL v5.1.61,或在RDS上使用:
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: e
type: ref
possible_keys: IDX_CUSTOMER_ENTITY_ENTITY_TYPE_ID
key: IDX_CUSTOMER_ENTITY_ENTITY_TYPE_ID
key_len: 2
ref: const
rows: 644775
Extra: Using where我知道,这些数据库版本中的差异很可能改变了查询优化器的工作方式,我也不知道这些版本有什么不同,但我正在寻找一种解决方案,帮助我们解决这些差异。
编辑:这里有一个参数的比较列表,我从旧主机复制到这个MySQL版本的默认参数。这些参数都没有影响上述结果,无论它们是否存在,或者我是否在RDS中使用了标准参数:

发布于 2014-11-08 20:58:50
查看您提供的查询,看起来您可能会被Bug #74030打断。一个补丁是为更高版本(5.6.20和5.7.4)提供的,但是还没有应用到发布说明。登录并投票给那个窃听器可能会更好。
现在,尽管我感到很痛苦,但您的顾问小组可能是对的(可能是意外的),..until应用了修补程序。
发布于 2014-11-04 23:51:39
我押注于MySQL conf:
发布于 2014-11-04 15:47:20
这类似于文档中提到的一个例子,即优化器无法计算出适当的索引,因为用于选择数据的键与用于排序数据的键不同。
我不能从一个版本到另一个版本进行任何更改,但下面是针对这种情况的简介:
在某些情况下,MySQL不能使用索引来解析ORDER,尽管它仍然使用索引查找与WHERE子句匹配的行。这些案件包括: 用于获取行的键与顺序中使用的键不相同:
SELECT * FROM t1 WHERE key2=constant ORDER BY key1;
这是问题中的文档,它提供了一些纠正问题的建议。我不知道你已经试过什么了。
https://stackoverflow.com/questions/26664145
复制相似问题