【问题标题】:MySQL : Using EXPLAIN keyword to know about indexing. (Specific Use Case)MySQL:使用 EXPLAIN 关键字来了解索引。 (具体用例)
【发布时间】:2017-01-29 16:06:07
【问题描述】:

这是我的表结构:

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 

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

索引被定义为:

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。这是什么意思 ?是否实际使用了索引?如果不是我做错了什么?

【问题讨论】:

    标签: mysql optimization indexing explain


    【解决方案1】:

    它正在使用您在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 中的列,这会强制重新调整表的物理顺序。这一事实很好地说明了为什么 id INT AUTO_INCREMENT PRIMARY KEY 经常被用作最佳实践用例,因为它永远不会经历重新洗牌并且很薄(4 字节)。

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

    这并不是说您不应该在二级索引ABCDE 这样的列上使用键。但总的来说,这对PK 来说不是一个好主意。

    请注意,可能有人认为ABCDE 永远不会为您的 PK 带来任何好处,因为范围查询在接近尾声时停止使用它,而只有 WHERE 退出范围命中日期。只是一个想法。

    文章Using EXPLAIN to Write Better MySQL Queries 是一篇不错的阅读文章。

    【讨论】:

    • 至于 const 对 Shadow 的评论,请在此处查看我的回答:stackoverflow.com/a/39419835
    • 如果我用唯一键替换 PK 怎么办?它对整体架构和改组有帮助吗?是的,我只处理一张表,没有参考。
    • PK 是唯一的密钥。只要努力使它们变薄且不变。
    • 对于像我这样的初学者来说,您的帖子信息量太大。 Wish本可以再给你一个赞成票。谢谢 ! .需要注意的一点是索引正在工作并且PK应该尽可能这样?对吗?
    • 索引正在工作。问题是您在使用USE INDEX (ABCDE) 强制使用的二级索引中几乎有2 个索引没有额外的好处。在较小的桌子上不会惊天动地。在巨大的表上丢弃不需要和未使用的索引。 PK要瘦。所以,我要做的是让你的 PK 像描述的那样是 int,并让你的ABCDE。但请注意,索引选择由所有查询的完整数组控制。不止一个。选择它们以影响对最终用户最重要的主要/经常/基本查询。
    【解决方案2】:

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

    key(JSON 名称:key)

    key列表示MySQL实际决定的key(索引) 使用。如果 MySQL 决定使用 possible_keys 索引之一 查找行,该索引被列为键值。

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

    【讨论】:

    • 其实让我担心的是,当我将 "playing_date BETWEEN '2016-09-01' AND '2016-09-13' " 更改为 ""playing_date = ''2016-09-13 " 时, ref 列填满了“const, const, const, const”。为什么会这样?
    • 因为在这种情况下,您的 where 条件中将有 4 个常量。这些常量用于比较索引列的值。
    • 为什么当我使用 BETWEEN 时它不显示“const, const, const, const”?
    • @DanishBinSofwan 因为如我的评论部分所示,评论一个链接,一个常量:“表格最多有一个匹配行”。 BETWEEN 范围不会发生这种情况。
    猜你喜欢
    • 2011-08-24
    • 2014-01-09
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 2021-02-21
    • 1970-01-01
    • 2021-11-16
    相关资源
    最近更新 更多