分区将如何影响我在 MySQL 中的当前查询?什么时候对我的表进行分区?

How will partitioning affect my current queries in MySQL? When is it time to partition my tables?

我有一个 table,包含 150 万行,39 列,包含大约 2 年的销售数据,并且每天都在增长。 在我们将它移到新服务器之前我没有遇到任何问题,我们现在的内存可能更少了。

查询当前需要很长时间。有人建议对导致大部分性能问题的大型 table 进行分区,但我有几个问题。

  1. 将我描述的 table 进行分区是否明智? 可能提高其性能?
  2. 如果我对它进行分区, 我必须更改我当前的 INSERT 或 SELECT 语句或 他们会继续以同样的方式工作吗?
  3. 是否分区 需要很长时间才能执行?我担心性能缓慢, 中途会发生一些事情,我会丢失数据。

  4. 我应该将它分成几年还是几个月? (我们通常 查看一个月内的数字,但有时我们需要数周或 年)。我还应该对列进行分区吗? (我们有一些 我们很少或从不使用的列,但我们可能想使用它们 稍后)

在大多数情况下,最好使用 indexes 而不是分区作为查询优化的主要方法。

关于 MySQL 中的分区,您应该了解的第一件事是这条规则:

All columns used in the partitioning expression for a partitioned table must be part of every unique key that the table may have.

在此处阅读有关此规则的更多信息:Partitioning Keys, Primary Keys, and Unique Keys

此规则使许多 table 不符合分区条件,因为您可能希望按不属于 table 中的主键或唯一键的列进行分区。

要知道的第二件事是分区只帮助查询使用明确让优化器推断哪些分区保存您感兴趣的数据的条件。这称为分区 P运行ing。如果您 运行 可以在任何或所有分区中找到数据的查询,MySQL 必须搜索所有分区,并且与常规的非分区 table 相比,您不会获得任何性能优势。

例如,如果您按日期分区,然后 运行 查询与特定用户帐户相关的数据,则必须搜索所有分区。

事实上,在这样的查询中使用分区 table 甚至可能 慢一点 ,因为 MySQL 必须搜索每个连续分区。

您问 table 分区需要多长时间。转换为分区 table 需要 ALTER TABLE 来重构数据,因此它所花费的时间与添加列所花费的时间大致相同。两种类型的更改都需要将数据复制到新的 table 空间。

(我同意比尔的回答;我将以不同的方式处理这个问题。)

When is it time to partion my tables?

可能永远不会。

is it likely to improve its performance?

更有可能稍微降低性能。

I have a table that contains 1.5 million rows

不够大,无法进行分区。

Queries are currently taking a very long time

通常那是因为缺少一个好的索引,可能是'composite'一个。 其次是查询的提法。请向我们展示一个慢速查询,以及 SHOW CREATE TABLE.

data of around 2 years, and grows every day

您最终会清除 "old" 数据吗?如果是这样,PARTITION BY RANGE(TO_DAYS(..)) 是个好主意。但是,它仅在清除期间有帮助。这是因为 DROP PARTITIONDELETE....

很多

we probably have less memory now.

如果你主要是看"recent"数据,那么内存的大小(cf innodb_buffer_pool_size)可能并不重要。这是由于缓存。但是,听起来您正在进行 table 扫描,可能是不必要的。

will I have to make changes to my current INSERT or SELECT

没有。但是您可能需要更改PRIMARY KEY和辅助键中的列。

Does the partition take a long time to perform?

慢 - 是的,因为它会复制整个 table。注意:这意味着额外的磁盘 space,分区的 table 将占用更多磁盘。

something would happen midway through and I would lose the data.

别担心。新的 table 已创建,然后很快 RENAME TABLE 将其交换到位。

Should I be partioning it to years or months?

经验法则:目标是大约 50 个分区。对于“2 年且不断增长”,可能的选择是 "monthly"。

we usually look at the numbers within the month, but sometimes we take weeks or years

闻起来像典型的 "Data Warehouse" 数据集?使用每日统计数据构建并逐步扩充 "Summary table"。有了 table,您可以快速获得 weekly/monthly/yearly 统计数据——速度可能提高 10 倍。适用于任何日期范围。这也对 "low memory".

有很大帮助

And should I also partition the columns? (We have some columns that we rarely or never use, but we might want to use them later)

你应该'never'使用SELECT *;相反,请指定您实际需要的列。 "Vertical partitioning" 是您建议的术语。它有时 实用。但我们需要看到 SHOW CREATE TABLE 具有实际的列名 才能进一步讨论。

关于分区的更多信息:http://mysql.rjweb.org/doc.php/partitionmaint
有关摘要 table 的更多信息:http://mysql.rjweb.org/doc.php/summarytables