【问题标题】:How should mysql be optimized/tuned for lots of writes and few reads (100:1). Read perf reqdmysql 应该如何针对大量写入和少量读取进行优化/调整 (100:1)。读取性能要求
【发布时间】:2009-06-14 14:14:48
【问题描述】:

我有一个简单的数据库,有 4 个表,每个表有几百万行,还有几个索引。我每分钟执行数百次更新和插入。读取频率要低得多,但它们需要快速 - 对于 Web 应用程序。读取应该有优先权——我可以延迟写入,如果它有助于提高读取的速度。

目前,当我不编写插入和更新时,选择都很好。当我同时写作时,事情可能会变慢 - 有时会很慢。服务器肯定会受到 IO 限制 - 我使用 iostat 并看到在高写入期间磁盘单元化率为 99%。

明天我将尝试削减一两个索引,缩小行大小,并禁用查询缓存。关于如何调整表或 mysql 本身以实现大量写入和少量读取,是否有人有任何其他建议?

表当前设置为使用具有紧凑行的 innodb 引擎,除了缓冲池大小之外,大部分配置仍设置为默认值。 db 将继续快速增长,因此不能将其全部放在 ram 中。

更新:它在 slicehost.com - 1gb ram,raid 10。

【问题讨论】:

    标签: mysql performance optimization innodb


    【解决方案1】:

    索引会减慢写入速度,但对于读取性能来说是必需的,因此您可以使用尽可能少的索引来支持读取。你的clustered index 会导致很多减速吗?

    另一种可能性是从您的写入中读取单独的数据库/表并选择最终一致性 - 这在您的情况下可能是不可能的。

    【讨论】:

    • 聚集索引如何导致速度变慢?这是一个大整数,因此向二级索引添加最小长度。我会介意大多数新写入是否仅在 3 分钟内可用 - 大多数不需要立即可用。
    • 抱歉 - 我在上面说了“我会介意”。我的意思是“我不介意”。
    • 如果聚集索引由于插入顺序而导致更多写入,则会导致速度变慢。如果它是一个自动递增的 big-int,那么您应该不会在那里看到问题。
    • 它不是自动递增的,但通常应该递增 - 大多数条目接近最大值。
    【解决方案2】:

    需要考虑的一件事(很多)是使用事务。如果您可以将多个写入操作捆绑在一个事务中,则应该会减少磁盘访问次数。

    【讨论】:

    【解决方案3】:

    不幸的是,MySQL 通常是为 80/20 的读/写比率而构建的。不知道有没有很多可以做的。

    你在使用交易吗?

    如果你选择的数据不经常受到写入的影响(这样在有修改的时候在写入时修改它不会影响写入性能),你可以在写入时将其外部化,例如在交易结束时。

    【讨论】:

    • 我还没有在多次写入时使用事务,但我明天会将它们批处理到事务中,看看是否有帮助。我还将考虑根据dev.mysql.com/doc/refman/5.1/en/innodb-tuning.html 增加日志大小和日志缓冲区
    • 好的,请稍后给我们反馈。
    【解决方案4】:

    我认为您需要考虑分区。这几乎是扩展写入的唯一方法。 MySQL 从 5.1 及以后的版本中为此提供了native support,但也可以推出自己的解决方案。后者要复杂得多,所以如果可能的话,我建议使用内置支持。但是,考虑到您过多的写入负载,这可能还不够。但是,如果不知道数据的结构,很难给您更详细的建议。

    【讨论】:

    • 哇——我完全误解了分区是什么,所以直到现在才开始阅读它。听起来不错——明天试试。感谢您的建议。
    • 您可能还想搜索“分片”。它与分区几乎相同,但强调它是一种自定义解决方案。我认为您可以通过这种方式找到更多资源。
    【解决方案5】:

    我建议你通过设置一个mysql主从配置来进行读写分离。

    您写入主服务器并将读取重定向到从服务器。

    拆分本身可以通过两种方式完成

    1. 使用代理(MySQL 代理、Continuent/Sequoia、..)
    2. 在您的应用程序中自行拆分

    【讨论】:

    • 对我来说似乎毫无意义。所有服务器仍然必须处理相同的写入负载。如果读取不频繁,复制似乎不太可能有帮助。
    • 感谢您回复此 Emil。如果可以的话,我想避免毫无意义的追逐。你可能在这里为我节省了几个小时。有人同意 Jitter 的建议吗?
    • Galera Cluster(3 个可写节点)和“RBR”可能会对写入扩展提供一点帮助。
    【解决方案6】:

    如果 MySQL 支持索引填充因子,那将是一个值得关注的领域。不幸的是,第 5 版不支持填充因子(显然它在 6.x 版的 feature request 列表中)。

    • 删除所有未使用的索引并限制索引的宽度会有所帮助。

    • 检查服务器有多少内存。

    • 磁盘是否经过 RAID?

    【讨论】:

    • 服务器有 1gb 内存,并且在 Raid 10 上。我将无法继续增加内存以适应 db - db 将继续增长。有最低要求吗? RAID 起什么作用?
    • @Tim Haines:1GB 很小。建议您至少使用 2GB
    【解决方案7】:

    你已经做了一些有用的事情(更少的索引,更小的数据类型)

    • innodb_buffer_pool_size 应该是可用 RAM 的 70% 左右。 (在旧版本中,默认值太低。)但是对于您的小型服务器(1GB RAM),150M 可能太大了。考虑获得更多 RAM。
    • 如果您要进行交换,请获取更多 RAM 或降低更多设置。
    • 考虑 innodb_flush_log_at_trx_commit = 2 -- 速度更快,但数据安全性较低
    • 批量插入 -- 单个查询中 100 次插入的运行速度是 100 次单行插入的 10 倍。
    • 查看规范化或非规范化
    • 检查函数调用中是否隐藏索引列:WHERE DATE(col) = '2019-01-01'
    • 使用慢日志来识别最顽皮的查询——它们可能是写读。
    • 我是否建议获得更多 RAM?

    还有很多其他的提示,但最好能看到最差的查询,再加上SHOW CREATE TABLE

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-08-04
      • 1970-01-01
      • 2012-07-16
      • 2012-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-19
      相关资源
      最近更新 更多