【问题标题】:Ways to optimize MySQL table [closed]优化 MySQL 表的方法 [关闭]
【发布时间】:2017-02-11 06:20:23
【问题描述】:

我有一张大桌子,桌子的大小以 GB 为单位,大约 130 GB。每天的数据都转储到表中。

我想优化表格...谁能建议我应该怎么做?

任何意见都会有很大帮助。

【问题讨论】:

  • 删除一半的记录?说真的,如果你想要一个严肃的回应,我认为你需要添加更多信息。
  • @DBA 向我们展示create table 语句和一些您想要加速的查询。
  • 感谢您的快速回复..pekka 和 Johan。 @Pekka - 实际上我无法删除任何内容,因为我需要数据。 @Johan - 数据太多了,我什至不知道该表中有多少行。但它以十亿为单位......该表已在 InnoDB 存储引擎中创建。表上有6个索引,其中一个是复合索引。
  • 也许你不能删除但它都需要存储在同一个表中吗?优化表的唯一原因是查询运行得更快 - 但您没有提供当前正在运行的查询的任何详细信息,也没有提供表的结构,也没有提供使用模式。
  • 优化我的唯一目的不是提高查询性能。当我试图在这个特定的表上触发查询以获取所有数据时,我的意思是选择 * 或选择 Count(*)。 mysql 服务器消失。

标签: mysql optimization


【解决方案1】:

这取决于您尝试如何优化它。

对于查询速度,包括多列索引在内的适当索引将是一个很好的起点。一定要解释你所有的查询,看看是什么占用了这么多时间。优化读取数据的代码以存储数据而不是重新查询。

如果旧数据不太重要,或者您要处理的数据过多,您可以按年、月、周或日轮换表格。这样,数据写入始终是一个非常小的表。较旧的表都已过时(即 tablefoo_2011_04),因此您有积压。

如果您尝试在同一个表中优化大小,请确保您使用了适当的类型。如果您获得可变长度字符串,请使用 varchar 而不是静态大小的数据。不要使用字符串作为状态指示符,使用带有辅助查找表的 enum 或 int。

服务器应该有很多内存,这样它就不会一直在磁盘上。

您还可以考虑使用缓存层,例如 memcached。

有关实际问题是什么、您的情况以及您尝试优化的内容的更多信息会有所帮助。

【讨论】:

  • 嗨,埃文,感谢 scuh 的详细解释。好吧,是的,旧数据很重要,但我可以将它与当前表分开。并将其存储在逐年表中。但是一年仍然有大量数据……有索引。在一天之内,大约有近百万条记录被插入。现在修改表格设计是个好主意..它不会破坏数据吗?
  • 这取决于您所做的更改。对于任何类型的表修改,您应该始终先进行备份。如果一年太长,如果需要,您可以使用月表甚至日表。最安全的做法是创建一个正确类型的新列。然后更新列,使新列等于原始列。然后验证数据是否正确。然后删除原始列。您可以编写更新以适当的方式转换数据。
【解决方案2】:

如果您的表是一种记录表,则可以有多种优化策略。

(1) 仅存储基本数据。

  • 如果其中没有必要的 - 可为空的 - 列并且它们不用于聚合或分析,请将它们存储到其他表中。保持主表更小。
  • Ex) 不要存储原始 HTTP_USER_AGENT 字符串。预处理代理字符串并存储您确切想要查看的较小数据。

(2) 将表格设为固定格式。

  • 对几乎固定长度的字符串使用 CHAR 然后 VARCHAR。这将有助于加快 SELECT 查询。
  • 例如)ip VARCHAR(15) => ip CHAR(15)

(3) 对旧数据进行汇总,定期转储到其他表中。

  • 如果您不必每天查看整个数据,请将其划分为定期表(年/月/日)并存储旧的汇总数据。
  • 例如)Table_2011_11 / Table_2011_11_28

(4) 大表不要使用过多的索引。

  • 索引过多会导致插入查询的负载过重。

(5) 使用 ARCHIVE 引擎。

【讨论】:

    【解决方案3】:

    您应该向我们展示您的 SHOW CREATE TABLE 表名输出的内容,以便我们查看列、索引等。

    乍一看,似乎 MySQL 的 partitioning 是您需要实现的,以进一步提高性能。

    【讨论】:

      【解决方案4】:

      一些可能的策略。

      如果数据集如此之大,它可能用于冗余存储某些信息:如果某些记录的访问频率比其他记录高得多,则保留缓存表,非规范化信息(限制连接数量或创建具有较少连接数的表)列,这样您就可以在内存中始终保留一个精简表),或者保留摘要以快速查找总计。

      汇总表可以通过定期生成它们或使用触发器来保持同步,或者甚至通过拥有一个可以计算实际总数和汇总的最近一天的缓存表来组合两者对于历史数据......将给你完整的精度,而不需要阅读完整的索引。测试以查看在您的情况下提供最佳性能的方法。

      按句点拆分表格当然是一种选择。这就像分区,但Mayflower Blog 建议您自己做,因为 MySQL 实现似乎有一定的限制。

      除此之外:如果这些历史表中的数据从未更改并且您想减少空间,则可以使用myisampack。支持索引(您必须重建)并报告了性能提升,但我怀疑您会提高读取单个行的速度,但会面临大型读取的性能下降(因为很多行需要解包)。

      最后:您可以从历史数据中考虑您需要什么。它是否需要与您最近的条目完全相同的信息,或者是否有一些不再重要的东西?我可以想象,如果你有一个访问日志,例如,它存储了各种信息,如 ip、引用 url、请求的 url、用户代理……也许在 5 年后用户代理根本不感兴趣, 可以将来自一个 ip 的一页 + css + javascript + 图片的所有请求合并到一个条目中(对于精确文件可能有不同的多对一表),并且引用 url 只需要出现次数并且可以与确切的时间或 ip 解耦。

      【讨论】:

        【解决方案5】:

        不要忘记考虑存储数据的介质的速度。我认为您可以使用 RAID 磁盘来加快访问速度,或者将表存储在 RAM 中,但在 130GB 时这可能是一个挑战!然后也考虑处理器。我知道这不是您问题的直接答案,但它可能有助于实现您的目标。

        【讨论】:

          【解决方案6】:

          您仍然可以按照@Evan 的建议尝试使用表空间或“每周期表”结构进行分区。

          如果您的全文搜索失败,可能应该转到 Sphinx/Lucene/Solr。外部搜索引擎绝对可以帮助您获得更快的速度。

          如果我们谈论的是表结构,那么您应该尽可能使用最小的数据类型。 如果optimize table 太慢并且对于非常大的表确实如此,您可以备份该表并恢复它。当然,在这种情况下,您将需要一些停机时间。

          作为底线: 如果您的全文搜索问题比应用任何表格更改之前的问题尝试使用外部搜索引擎。

          【讨论】:

            猜你喜欢
            • 2015-03-03
            • 2020-12-29
            • 1970-01-01
            • 1970-01-01
            • 2012-04-28
            • 2012-11-10
            • 1970-01-01
            • 2018-04-14
            • 1970-01-01
            相关资源
            最近更新 更多