更改数据库版本后,将不会自动使用索引

Rob*_*ill 7 mysql database magento amazon-web-services mysql-5.6

我们最近将Magento应用程序从私有主机迁移到AWS Web服务.我们注意到Magento的一些内部功能在迁移后需要花费相当长的时间才能执行,因此开始调查.

其中一个查询是一个简单的客户选择查询,对属性表有大约9-10个常规连接以获取属性.

我们对查询进行了一些测试,发现旧主机和AWS之间的区别在于旧主机上,MySQL优化器似乎使用正确的索引,而在AWS中,它使用filesort,忽略索引.

使用FORCE INDEX(index_name)使得查询在AWS中正确执行,但是我们不想走这条路,而是宁愿在数据库配置中修复问题,而不是在我们的Magento应用程序中进行手动破解.要清楚,不是我们的索引的问题,它们是正确设置的.

背景:

  • 我已将所有MySQL参数从旧主机的my.cnf文件复制到RDS中的参数组,但没有任何区别
  • 这些表都是InnoDB
  • 我运行分析,修复和优化查询等
  • 在RDS上完成查询大约需要45秒
  • 查询在旧主机上完成大约需要2秒钟,或者当我FORCE INDEX()用来强制RDS的行为方式与旧主机相同时

旧的MySQL服务器运行的是版本5.1.61,我们运行的AWS RDS实例是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;
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

旧主机 - MySQL v5.1.61,或FORCE INDEX在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
Run Code Online (Sandbox Code Playgroud)

我知道这些数据库版本的差异很可能改变了查询优化器的工作方式,我不知道这些版本的差异是什么,但我正在寻找一个有助于解决方案的解决方案我们要解决这些差异.


编辑:这是RDS的比较列表,其中包含我从旧主机复制的参数与此MySQL版本的默认参数.这些参数都没有影响上面的结果是否存在或者我是否在RDS中使用了标准参数:

在此输入图像描述

Ste*_*ert 1

查看您提供的查询,看起来您可能被Bug #74030所困扰。为更高版本(5.6.20 和 5.7.4)提供了补丁,但尚未应用,请查看发行说明。登录并为该错误投票可能会很好。

目前,尽管让我很痛苦,但您的顾问小组可能是对的(也许是偶然的)……直到应用补丁为止。