【问题标题】:MySQL query slow querying table on primary keyMySQL查询主键上的慢查询表
【发布时间】:2011-06-02 02:39:17
【问题描述】:

所以我有一个基本上像 NoSQL 设置一样使用的表。结构是:

id bigint 主键 数据介质块 修改时间戳

它有大约 350k 行。在其上运行的查询的结构如下:

从id=XXX的表中选择数据;

表引擎是 InnoDB。我注意到有时针对此表运行的查询相当慢。有时它们需要 3 秒才能运行。该表在磁盘上是 3 GB,我给了 innodb_buffer_pool_size 4G。

这里有什么我遗漏的吗?我可以调整任何设置来提高性能吗?

编辑:按要求解释输出:

+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table    | type  | possible_keys | key     | key_len | ref   | rows | Extra |
+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+
|  1 | SIMPLE      | cache    | const | PRIMARY       | PRIMARY | 8       | const |    1 |       |
+----+-------------+----------+-------+---------------+---------+---------+-------+------+-------+

创建表:

CREATE TABLE `cache` (
  `id` bigint(20) unsigned NOT NULL DEFAULT '0',
  `data` mediumblob,
  `modified` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

【问题讨论】:

    标签: mysql innodb


    【解决方案1】:

    我最初在这里看到了两个问题。首先是您有一个带有 blob 数据类型的查询。当涉及到数据检索时,这将导致速度问题。其次,您使用的是 InnoDB,它针对写入进行了优化。这意味着虽然它可能是整体上的最佳选择,但在极端读取情况下,它的性能可能不如 MyISAM。这些问题都不一定是交易杀手,但它们确实都会增加性能损失。但是,除此之外,我不确定我是否可以在不先让您进行分析的情况下为您提供更好的优化答案。这就是我建议你首先做的事情。分析您的查询以确定执行计划是什么,然后确定执行计划为何如此缓慢。

    这是一个很好的 MySQL 优化“前 10 名”列表。至少有一对直接适用于您的情况:

    http://20bits.com/articles/10-tips-for-optimizing-mysql-queries-that-dont-suck/

    这是另一篇关于服务器设置的优秀优化文章(专门针对 InnoDB):

    http://www.mysqlperformanceblog.com/2007/11/01/innodb-performance-optimization-basics/

    根据您提供的 CREATE TABLE 语句,我确实想到了您应该解决的另一件事(同样,不是查询杀手,而是另一个性能损失)。除非有将 bigint 用于您的 ID 字段的商业案例,否则请选择 int。一个 int 将允许 21 亿行,所以你不应该用完数字。进行此切换将节省磁盘空间并提高查询性能。这是一篇关于它的文章:

    http://ronaldbradford.com/blog/bigint-v-int-is-there-a-big-deal-2008-07-18/

    【讨论】:

    • innodb 并非仅针对写入进行优化——一个设计良好的 innodb 表利用它的聚集索引将胜过任何其他引擎stackoverflow.com/questions/4419499/…
    • 我不确定我是否同意 InnoDB。我的设置与第二个链接所建议的非常接近。
    • 对不起,我想我有点不清楚。与 MyISAM 相比,InnoDB 对写入进行了更好的优化,MyISAM 对读取进行了更好的优化。 InnoDB 可能是你最好的选择,我只是想说从阅读的角度来看它不是最好的选择。
    • 是的,我也不是 bigint 的粉丝。甚至不可能为我们正在做的事情用完一个 int。但这并不是我的决定。
    • @Jon - 明白了。我们都处理这样的问题。快速提问 - 您说您将其视为 NoSQL 文件。这是否意味着您正在从应用程序调用查询?如果是这样,它是本地的还是跨网络的?与实际调用本身相比,瓶颈可能是传输或处理吗?
    【解决方案2】:

    尝试使用尽可能小的 id 大小。如果它是一个您知道永远不会大于几百万的数字键,您可以使用 MEDIUMINT UNSIGNED 并在 INT 上为每条记录保存一个字节,这可能会加快搜索速度。尽管如此,对于 350,000 行来说,3 GB 还是非常多的。

    听起来您还可以通过使用partitioning feature 将表拆分为逻辑单元来获得一些好处。您可能特别想搜索“mysql 垂直分区”;如果存在您不经常访问的大列,将它们移到单独的表中并仅在需要时查询会更有效。

    【讨论】:

    • 嗯,这里的整个想法是只进行一次查询来获取数据。结果只是比我希望的要慢得多。不确定 int 大小对我有多大作用。
    • 诚实吗?可能不会,但它可能会稍微提高您的查询速度。我真的认为垂直分区是要走的路,因为听起来你的行比较大。不幸的是,MySQL 本身不支持垂直分区,因此您不得不使用多个表来模拟它。我希望我能提供更多帮助。
    【解决方案3】:

    您能否发布您的CREATE TABLE 声明以及EXPLAIN select data from table where id=XXX 的输出?系统上的io等待如何?

    我的最佳猜测是您受 IO 限制,并且由于行的大小不完全相同,因此必须搜索数据。您有足够的内存,它应该能够保持数据缓存。此链接描述了 MySQL 中可能有用的一些低级分析。

    http://dev.mysql.com/tech-resources/articles/using-new-query-profiler.html

    【讨论】:

      【解决方案4】:

      我会寻找的东西:

      • 慢查询什么时候出现?

        • 是在重新启动 DB 之后吗?那么这可能只是一个临时问题 - 查询在冷缓存中命中
        • 是在 DB 转储/加载期间吗? - 然后更改备份策略 - 例如使用复制,或添加更多磁盘 IO(在 RAID 中添加更多磁盘、将磁盘更改为 SSD、在多个磁盘上重新分区系统等)
        • 是在读/写高峰期吗?复制在这里也可能有所帮助 - 写入主服务器并负载平衡主服务器和从服务器之间的读取
      • 另外 - 那里真的需要那个 mediumblob 吗?

      【讨论】:

      • 它们在一天中偶尔发生。数据库已经启动了一段时间。我们不备份这些数据,因为它只是一个可以重建的缓存。中等 blob 表。其中的数据是拥有表格的全部目的。
      猜你喜欢
      • 2020-10-22
      • 1970-01-01
      • 1970-01-01
      • 2012-12-15
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多