【问题标题】:mysql query slow after MyISAM -> InnoDB and move to AWSMyISAM -> InnoDB 后 mysql 查询速度变慢并移至 AWS
【发布时间】:2017-01-27 05:19:57
【问题描述】:

我计划从共享托管服务器切换到 AWS 设置(EC2 用于 apache/php,RDS 用于 MySQL)。

我的 php/mysql 站点的测试版在共享服务器上运行了一年多。特别是一页在浏览器中总是运行得很快(完全加载可能

在准备迁移时,我将数据库和所有表从 MyISAM 更改为 InnoDB。我还将默认字符集切换为 utf8mb4(是 latin-1 或其他),并将排序规则切换为 utf8mb4_unicode_ci。有几个类似于 varchar2(400) 的列被索引,导致 > 191 字符错误(因为使用 utf8mb4 从 3byte->4byte 移动)。我进去并手动将这些列切换到 UTF-8/utf_unicode_ci。一切似乎都很好(没有明确的错误)

现在,我已将站点/数据库的副本移至 AWS。大多数页面加载正常。特别是这个需要永远加载(> 5分钟)。我有一些非常小的 EC2 实例和 RDS 实例,所以我意识到这可能是一个问题,但我是唯一一个使用该站点(用于一个查询)的人,整个数据库小于 70MB。

运行解释计划显示在大多数情况下使用键(索引?)和一个具有 74k 行的“派生”表。 74k 是一个非常小的数据集。我对 Oracle 解释计划更加熟悉,所以我很难弄清楚发生了什么。

我尝试在共享主机服务器上运行原始页面,但速度也慢了很多!因此,我没有理由相信这是 AWS 问题。

我知道 MyISAM 在简单的场景下会快一点,但它不可能比我新使用的 InnoDB 快 10000000000000 倍?

在尝试为超过 191 个字符的 varchar 建立索引时,转换是否出现问题?是否有可能只是以某种方式破坏了系统/表格?如果您给它们大量时间,查询将完成,但它们不可能这么慢。我认为即使索引被炸掉并且它正在对 74k 行进行全表扫描,它也不应该出汗。

想法?

编辑: 找到这个线程: https://dba.stackexchange.com/questions/75091/why-are-simple-selects-on-innodb-100x-slower-than-on-myisam 发帖人似乎也有类似的减速体验。我不能使用与他/她相同的解决方案。认为我必须将所有要返回的列放入索引中是很疯狂的。这不可能是每个人都接受的吗?

【问题讨论】:

标签: mysql innodb amazon-rds myisam


【解决方案1】:

好的,我想通了。是我的错(不足为奇)。在我真正知道自己在做什么之前,我很久以前就写了这个查询。肯定有改进的余地...

查询看起来像:

TableA (main table of focus)
  aID (pk)
  bID (fk)
  locationID (fk)
  rowTitle

TableB 
  bID (pk)
  locationID (fk)

TableLocations
  locationID (pk)
  locationName

我想基本上使用 A 的位置(如果存在),但如果 A 没有位置,则回退到 B 的位置。 (A 将始终链接到 B)。

我正在做一些类似的事情

 SELECT
   rowTitle,
   locationName
 FROM
   TableA a, TableB b, TableLocations loc
 WHERE
  a.bID = b.bID
  AND
  ( a.locationID = loc.locationID
    OR 
   (a.locationID IS NULL AND b.locationID = loc.locationID)
  )

它运行良好,并且在使用 MyISAM 时总是返回我想要的。而且速度非常快。但是,由于某种原因,当我移至 InnoDB 时, sh$& 碰壁了。在执行此查询的计划时,不知道引擎有何不同。我想当数据集足够大时,MyISAM 会在某个时候窒息,但由于我仍在 dev/uat 中,因此数据很小。

我后来转向结构更好的东西,例如:

 SELECT 
   rowTitle
   CASE WHEN loc1.locationID IS NOT NULL THEN loc1.locationName
        WHEN loc2.locationID IS NOT NULL THEN loc2.locationName
   END as locationName
FROM
   TableA a
JOIN TableB b ON a.bID = b.bID
 LEFT OUTER JOIN TableLocations loc1 ON a.locationID = loc1.locationID
 LEFT OUTER JOIN TableLocations loc2 ON b.locationID = loc2.locationID

一切都很好!我删除了很多查询和其他表格,以专注于我的主要逻辑/物理问题。

查询减少到大约 10 毫秒,这是我所期望的。

这是我对 MySQL 又爱又恨的一件事。有时“它只是工作”,让你看看自己的不足之处。绝对是我的错,因为第一次没有做对......

附加问题: 如果有人知道 MyISAM 与 InnoDB 如何评估第一个(坏)查询之间的区别以及为什么性能如此不同,我真的很想听听!

谢谢!

【讨论】:

  • 那么...您的innodb_buffer_pool_size 的价值是多少?让我猜猜 - 128 MB? :) 如何查看:SHOW VARIABLES LIKE '%innodb_buffer_pool%';
  • 将 buffer_pool 更改为可用 RAM 的 70%,将 key_buffer_size 降低为 30M。
  • innodb_buffer_pool_size=625999872(AWS/RDS 设置的默认值)。
  • key_buffer_size=16777216(默认来自 AWS/RDS)
猜你喜欢
  • 1970-01-01
  • 2012-02-25
  • 2012-11-19
  • 2014-05-27
  • 2012-08-04
  • 2012-01-13
  • 2018-10-25
  • 2014-02-17
  • 2011-05-14
相关资源
最近更新 更多