【问题标题】:Mysql explain query scan more rows then what actual returnsMysql解释查询扫描更多行然后实际返回
【发布时间】:2018-07-30 16:53:20
【问题描述】:

我正在使用 mysql 5.6.22-log

我正在对表 aggr 执行查询,所有条件都在 where 子句中。

以下是数据

表格

CREATE TABLE aggr (
 a_date DATE,
 product_id INT(11),
 data_point VARCHAR(16),
 los INT(11),
 hour_0 DOUBLE(4,2),
 UNIQUE KEY `unique_row` (a_date,product_id,data_point,los),
 INDEX product_id(product_id)
);

插入查询

INSERT INTO aggr(a_date,product_id,data_point,los,hour_0) 
VALUES
('2018-07-29',1,'arrivals',1,10),('2018-07-29',1,'departure',1,9),
('2018-07-29',1,'solds',1,12),('2018-07-29',1,'revenue',1,45.20),
('2018-07-30',1,'arrivals',2,10),('2018-07-30',1,'departure',2,9),
('2018-07-30',1,'solds',2,12),('2018-07-30',1,'revenue',2,45.20),

('2018-07-29',2,'arrivals',1,10),('2018-07-29',2,'departure',1,9),
('2018-07-29',2,'solds',1,12),('2018-07-29',2,'revenue',1,45.20),
('2018-07-30',2,'arrivals',2,10),('2018-07-30',2,'departure',2,9),
('2018-07-30',2,'solds',2,12),('2018-07-30',2,'revenue',2,45.20);

查询

EXPLAIN 
SELECT * FROM aggr
WHERE a_date BETWEEN '2018-07-29' AND '2018-07-29' 
AND product_id = 1 
AND data_point IN('arrivals','departure' ,'solds','revenue') 
AND los = 1 ;

问题

  1. 以上查询扫描 8 行(而根据 where 条件,它应该只扫描 4 行)

预期结果:

它应该只扫描 4 行而不是 8 行。

有人能解释一下为什么mysql扫描8行而不是4行吗?

谢谢

【问题讨论】:

  • 你的问题是死锁。但是您问为什么它扫描 8 并返回 4。为什么您认为它应该扫描返回的行数?它说type = ALL。这意味着它会查看所有行。它不使用索引,因为对这么小的表使用索引会比较慢。表中有 8 行,因此它会查看所有行,确定由于 WHERE 而需要 4 行并返回这 4 行。
  • @N.B.表格共有 16 行。我已经在唯一键中使用的 where 子句中指定了所有条件。但它仍然扫描 8 行,而不是 4 或 16 行。
  • 大家好,提到有问题的死锁会造成很多混乱,我已经删除了那部分。
  • 我的评论仍然有效。没有规则说 MySQL 将扫描 X 行并返回 X 行。
  • @N.B.我并不是说你错了,但我要问的是,由于上述查询,如果我在两个不同的会话中使用相同的条件运行删除查询,那么在相同数据的事务锁定中删除查询。您可以查看 information_Schema.INNODB_LOCKS 表来验证 lock_data。

标签: mysql


【解决方案1】:

EXPLAIN 语句用于获取有关如何执行查询的信息。 rows 数字是仅近似值,查询优化器在构建执行计划时使用它来做出决策。它是数据库管理员或开发人员获取诊断信息的工具。

EXPLAIN 的结果实际上向您显示的是您的查询没有可用的索引(key(NULL))。这非常糟糕,可能会导致此查询显着变慢。通过查看您的表定义,我会说您需要为 data_point 单独索引,或者至少尝试使其成为主键的最后一列。

但是,这些都不足以解释死锁。我什至不确定你为什么在这里向我们展示EXPLAIN - 这与它无关。为了能够诊断死锁,您需要提供更多信息。从表的类型开始(MyISAMInnoDB 等)和SHOW FULL PROCESSLIST。然后,对于每个进程,查看它为每个表持有的锁。

【讨论】:

    猜你喜欢
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-01
    • 2016-01-05
    • 2018-08-19
    • 1970-01-01
    • 1970-01-01
    • 2014-01-18
    相关资源
    最近更新 更多