【问题标题】:Index on mysql partitioned tablesmysql分区表上的索引
【发布时间】:2017-02-21 07:03:23
【问题描述】:

我有一个有两个分区的表。分区为pactive = 1pinactive = 0。我知道两个分区并没有太大的收获,但我已经用它来截断和加载一个分区并在另一个分区中进行普通插入。

当我创建索引时,问题就来了。

查询是这样的

select partitionflag,companyid,activityname
from customformattributes
where companyid=47
      and activityname = 'Activity 1'
      and partitionflag=0

创建索引 -

create index idx_try on customformattributes(partitionflag,companyid,activityname,completiondate,attributename,isclosed)

将从上述查询中检索大约 200000 条记录。但是查询连同提到的索引需要 30 多秒。这么长时间的原因是什么?此外,如果从提到的索引中删除 partitionflag,则该索引甚至不会被使用。

而且是理解,

  1. 即使有可用的分区,优化器也需要在索引定义中提到所需的分区,以便它只命中所需的分区----正确吗?

任何关于理解这一点的想法都会非常有帮助

【问题讨论】:

  • 没有解释输出,我们只能猜测。
  • 嗨,请在下面找到计划详细信息 id - 1 select_type - SIMPLE table - customformattributes type - ref possible_keys - idx_try key - idx_try key_len - 213 ref - const, const, const rows - 247892 过滤 - 100.00额外 - 使用 where;使用索引
  • 我不认为查询执行计划有什么特别错误的地方。你有一个很大的结果集。您是否尝试过减少结果集并以这种方式检查查询性能?

标签: mysql performance indexing partition


【解决方案1】:

您可以通过重新排序其中的列来优化您的索引。通常索引中的列按其基数排序(从最高到最低)。基数是给定列中数据的唯一性。因此,在您的情况下,我认为 customformattributes 表中有许多 companyid 变体,而 partitionflag 的基数为 2(如果此列的所有选项都是 1 和 0)。 您的查询将首先过滤 partitionflag=0 的所有行,然后按公司 ID 等过滤。 当您从索引中删除 partitionflag 时,查询没有使用索引,因为可能是优化器决定进行全表扫描而不是使用索引会更快(在大多数情况下优化器是正确的)

对于给定的查询:

select partitionflag,companyid,activityname
from customformattributes
where companyid=47
  and activityname = 'Activity 1'
  and partitionflag=0

以下索引可能会更好(但当然:

create index idx_try on customformattributes(companyid,activityname, completiondate,attributename, partitionflag, isclosed)

对于使用索引的查询,必须满足以下规则 - 索引中最左边的列应该出现在 where 子句中......并且根据您使用的 mysql 版本,可能需要额外的查询要求。例如,如果您使用的是旧版本的 mysql - 您可能需要按照它们在索引中列出的顺序对 where 子句中的列进行排序。在 mysql 的最新版本中,查询优化器负责以正确的顺序对 where 子句中的列进行排序。

您的 SELECT 查询花费了 30 多秒,因为它返回 200k 行,并且索引可能不是给定查询的最佳索引。

关于分区的第二个问题:通常的规则是,您要分区的列必须是表中所有 UNIQUE 键的一部分(主键根据定义也是唯一键,因此该列也应添加到 PK 中)。如果表结构和逻辑允许您将分区列添加到表中的所有 UNIQUE 索引,那么您添加它并对表进行分区。 正确进行分区后,您可以利用分区修剪 - 这是当 SELECT 查询仅在存储给定数据的分区中搜索数据时(否则它会在所有分区中查找)

您可以在此处阅读有关分区的更多信息: https://dev.mysql.com/doc/refman/5.6/en/partitioning-overview.html

【讨论】:

  • 抱歉延迟回复..您的解释帮助我更好地理解索引..谢谢!!
  • 希望对您解决查询问题有所帮助。
  • 你能接受其中一个答案吗(如果你同意的话),这样问题就不会悬而未决了吗?
【解决方案2】:

查询很慢只是因为磁盘很慢。

在设计索引时,基数并不重要。

那个查询的最佳索引是

INDEX(companyid, activityname, partitionflag)  -- in any order

它是“覆盖”,因为它包括所有SELECT 中任何地方提到的列。这由EXPLAIN 中的“使用索引”指示。

省略其他 3 列会使查询更快,因为它必须从磁盘读取更少的内容。

如果您对查询进行任何更改(添加列、从 '=' 更改为 '>'、添加 ORDER BY 等),则索引可能不再是最佳的。

“此外,如果从提到的索引中删除分区标志,则甚至不使用索引。” -- 那是因为它不再“覆盖”了。

请记住,索引有两种使用方式——“覆盖”和作为查找数据的方式。当您没有“覆盖”索引时,优化器会在使用索引并在索引和数据之间跳转与简单地忽略索引并扫描表之间进行选择。

【讨论】:

  • 抱歉延迟回复..您的解释帮助我更好地理解索引..谢谢!!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-03-10
  • 1970-01-01
  • 2013-05-19
  • 2011-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多