【问题标题】:MySQL: Inner Join with Group By is creating a temporary table (doing a table scan)MySQL:Inner Join with Group By 正在创建一个临时表(进行表扫描)
【发布时间】:2018-04-24 00:55:07
【问题描述】:

我创建了一个产生正确结果的查询,但它正在执行全表扫描并创建一个临时表。 (使用临时;使用文件排序)。

我希望它使用索引,但是因为我使用 group by 来删除重复项,所以它不使用可用的索引。我试过删除 Group By 并使用 Distinct,但这并不能解决问题。

我使用的是多对多关系,因为一个员工可以有多个职位,而多个员工可以有相同的职位。

表格:

    CREATE TABLE IF NOT EXISTS `Employees` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `firstname` varchar(50) DEFAULT NULL,
  `middlename` varchar(7) DEFAULT NULL,
  `lastname` varchar(50) DEFAULT NULL,
  `city` varchar(50) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `firstname` (`firstname`),
  KEY `middlename` (`middlename`),
  KEY `lastname` (`lastname`),
  KEY `city` (`city`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `Employee_Position` (
  `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
  `employee_id` int(11) NOT NULL,
  `position_id` int(11) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `employee_id` (`employee_id`),
  KEY `function_id` (`position_id`),
  KEY `employee_id+position_id` (`employee_id`,`position_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

CREATE TABLE IF NOT EXISTS `Positions` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(20) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `name` (`name`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

查询:

SELECT 
    e.id, 
    e.firstname, 
    e.middlename, 
    e.lastname, 
    e.city 
FROM Employees AS e 
INNER JOIN Employee_Position AS ep 
    ON e.id = ep.employee_id 
WHERE (ep.position_id IN (1, 2, 3, 4)) 
GROUP BY e.id 
ORDER BY e.lastname

为什么这会创建一个临时表而不使用索引?有没有办法解决这个问题?

【问题讨论】:

标签: mysql sql indexing group-by inner-join


【解决方案1】:

您的查询进行了不必要的聚合。

这里有一个更好的方式来表达查询:

SELECT e.id, e.firstname, e.middlename, e.lastname, e.city
FROM Employees e 
WHERE EXISTS (SELECT 1
              FROM Employee_Position ep 
              WHERE e.id = ep.employee_id AND ep.position_id IN (1, 2, 3, 4)
             )
ORDER BY e.lastname;

您已经在employee_position(employee_id, position_id) 上拥有此查询的正确索引。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-30
    • 2016-12-04
    • 2011-07-01
    相关资源
    最近更新 更多