MySQL : 使用 EXPLAIN 关键字了解索引。 (具体用例)

MySQL : Using EXPLAIN keyword to know about indexing. (Specific Use Case)

这是我的 table 结构:

CREATE TABLE `channel_play_times_bar_chart` (
  `playing_date` datetime NOT NULL,
  `channel_report_tag` varchar(50) NOT NULL,
  `country_code` varchar(50) NOT NULL,
  `device_report_tag` int(11) NOT NULL,
  `greater_than_30_minutes` decimal(10,0) NOT NULL,
  `15_to_30_minutes` decimal(10,0) NOT NULL,
  `0-15_minutes` decimal(10,0) NOT NULL,
  PRIMARY KEY (`country_code`,`device_report_tag`,`channel_report_tag`,`playing_date`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

当我运行以下查询时:

EXPLAIN EXTENDED 
SELECT 
  channel_report_tag,
  SUM(`greater_than_30_minutes`) AS '>30 minutes',
  SUM(`15_to_30_minutes`) AS '15-30 Minutes',
  SUM(`0-15_minutes`) AS '0-15 Minutes' 
FROM
  channel_play_times_bar_chart USE INDEX (ABCDE) 
WHERE country_code = 'US' 
  AND device_report_tag = 14 
  AND channel_report_tag = 'DUNYA NEWS' 
  AND playing_date BETWEEN '2016-09-01' 
  AND '2016-09-13' 
GROUP BY channel_report_tag 
ORDER BY SUM(`greater_than_30_minutes`) DESC 
LIMIT 10 

这是我得到的输出(在另一个选项卡中打开它):

index 定义为:

CREATE INDEX ABCDE 
ON channel_play_times_bar_chart (
  `country_code`,
  `device_report_tag`,
  `channel_report_tag`,
  `playing_date`,
  `greater_than_30_minutes`
)

我在这里有点困惑; key 列显示 ABCDE 被用作 index,而 ref 列显示 NULL。这是什么意思 ?索引是否实际被使用?如果不是我做错了什么?

您的查询确实使用了 ABCDE 索引。正如 MySQL 关于 EXPLAIN Output Format 的文档所解释的那样 :)(粗体是我的):

key (JSON name: key)

The key column indicates the key (index) that MySQL actually decided to use. If MySQL decides to use one of the possible_keys indexes to look up rows, that index is listed as the key value.

解释输出的 ref 字段主要用于存在连接时显示与索引进行比较的字段/常量/表达式。

它正在使用您在 create index 中显示的密钥,即 ABCDE。 如果你做一个

就好了
show create table channel_play_times_bar_chart

并且一下子全部展示出来。该键可能对您没有多大用处,因为它复制了您相当广泛的主键已经为您提供的大部分内容。

一旦查询使用该键直至复合键的第 3 段,它将在该复合键的 playing_date 上以 WHERE 范围恢复并找到 8 行。

注意 EXPLAIN 是估计值。

此外,我会重新考虑您的 PRIMARY KEY (PK) 想法的策略,特别是考虑到您决定通过创建 ABCDE 来或多或少地欺骗它。这意味着您正在维护两个索引,而第二个索引几乎没有任何收获(您将一列添加到二级索引 ABCDE)。

PK 它相当宽(我相信是 118 字节)。它规定了物理顺序。如果在构建事物的整个过程中都使用这个想法,那么这个想法很容易成为一个糟糕的想法。通过 UPDATE 对数据所做的更改会影响 PK 中的列,从而强制重新调整 table 的物理顺序。这个事实很好地说明了为什么 id INT AUTO_INCREMENT PRIMARY KEY 经常被用作最佳实践用例,因为它永远不会经历重新洗牌并且很薄(4 字节)。

键的宽度及其使用 referencing(其他)tables(在外键约束中)的策略会影响键的大小和查找性能。宽键可以显着减慢该过程。

这并不是说您不应该在这些列(例如您的二级索引 ABCDE 上设置键。但总的来说,这对 PK.

来说不是一个好主意

请注意,可以说 ABCDE 永远不会给你 任何 优于你的 PK 的好处,因为范围查询在接近尾声时停止使用它,只是 WHERE 一旦达到日期,范围就会消失。只是一个想法。

这篇文章 Using EXPLAIN to Write Better MySQL Queries 读起来不错,而且相当简短。