【问题标题】:mysql inner join and wheremysql内部连接和在哪里
【发布时间】:2020-11-13 21:51:12
【问题描述】:

2 个表:以employee & employee_address 为例

提供了三个索引:

ALTER TABLE employee ADD INDEX `E_P` (`position`) USING BTREE;

ALTER TABLE employee_address ADD INDEX `EA_Z` (`zipcode`) USING BTREE;

ALTER TABLE employee_address ADD INDEX `EA_E` (`employee_id`) USING BTREE;

第一个内部连接

select * from employee_address ea
inner join employee e on e.employee_id = ea.employee_id and e.position = 'MANAGER'
where ea.zipcode > 30000

使用 where 子句的第二次内连接

select * from employee_address ea
inner join (
select * from employee e where e.position = 'MANAGER'
) e on e.employee_id = ea.employee_id 
where ea.zipcode > 30000

假设有: 每张表有 500000 条记录 1000个不同的位置 2000个不同的邮政编码

我发现查询 1 效率更高。

这两个查询有什么不同?

是否可以像在一张表中一样快速查询它? 以及如何?

select * from employee e where e.position = 'MANAGER' 
and e.zipcode > 30000

ALTER TABLE employee ADD INDEX `Z_P` (`zipcode`, `position`) USING BTREE;

【问题讨论】:

  • 使用EXPLAIN查看不同的查询计划。
  • 你应该在选择之前显示解释计划输出使用解释来获得输出。
  • @flyshell 。 . . MySQL 倾向于在 FROM 子句中实现子查询,这限制了这些表上索引的使用。
  • explain 已经过检查,但是我找不到与查询 3 的性能相匹配的解决方案

标签: mysql sql


【解决方案1】:

在第二个中,您正在预过滤然后加入。这打破了索引。 您基本上是在返回一个没有索引的要加入的新表。

如果您查看查询说明计划,您应该会看到 n2 中的连接。没有索引查找。

如果您想检查是什么让您放慢了速度以使用查询解释计划并学习阅读它在做什么,这通常是一个好主意。

【讨论】:

    【解决方案2】:

    查看您的代码示例,而不是您提出的索引,您可以尝试使用这些复合索引

    ALTER TABLE employee_address ADD INDEX ea_id_z (employee_id, zipcode) ;
    ALTER TABLE employee ADD INDEX E_P (position, employee_id) ;
    
    select * 
    from employee_address ea
    inner join employee e on e.employee_id = ea.employee_id 
    and e.position = 'MANAGER'
        and ea.zipcode > 30000
    

    在查询中,数据库引擎为每个表使用单个索引,因此您应该提供最具选择性的索引,并在 where/join 子句评估期间提供所需的大量信息
    那么使用适当的复合索引是最有效的

    为了更好的索引,最好在左侧添加最 macthing 列(在这种情况下是位置而不是邮政编码,因为经理使用相等的运算符)

    对于基于与子查询连接的第二次查询,子查询的结果作为临时表进行管理,索引用于内部选择,但对连接子句没有用处(在这种情况下,只有外部表的索引可以使用)

    【讨论】:

    • 在较新版本的 mariadb 和我相信 MySQL 中,每个非主索引都自动成为复合索引,并隐式添加了主键列。虽然可能不是 myisam。
    • no .. 复合索引不是自动创建的 .. 创建的 .. 复合索引是涉及多于一列的索引 ...并且不会自动创建您的评论不清楚并且是不清楚这与我的答案有何关系..可能您指的是一些限制..
    • 不,我的意思是我所说的。如果你有一个索引 foo (bar) 和一个主键 (baz,quux),那么 foo 实际上就是 (bar,baz,quux) 上的一个索引
    • @ysth 是的,这也是我对 InnoDB 表的理解
    • 即使使用了 ea_id_z,它只会使查询 e 更快。但是,如果结果很大(数百万条记录)。 reuslt 将是一个用于查询 ea 的临时表,它很慢?它仍然比 [query 3] 慢吗?
    猜你喜欢
    • 2017-05-20
    • 2011-07-13
    • 1970-01-01
    • 2013-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多