• 数据库笔记-IN、EXSITS 如何选择(小表驱动大表)


    小表驱动大表,即小的数据集驱动大得数据集。在知道什么是小表驱动达大表之前,我们先来了解两个查询关键字,IN 与 EXISTS。我们通过两段查询语句先来了解一下它们的作用。我建立了两张表,一张员工表,一张部门表,将这两张表关联起来。

    我们先使用IN 来查询数据:

    SELECT * 
    FROM t_emp 
    WHERE dept_id IN (SELECT dept_id FROM t_dept) 
    LIMIT 5;

    查询结果:这里我就只查询5 条数据。

    +-------------+----------+------------+--------------+---------+
    | emp_id      | emp_name | emp_gender | emp_email    | dept_id |
    +-------------+----------+------------+--------------+---------+
    | 00000000177 | 41d80    | m          | 41d80@zc.com |       1 |
    | 00000000178 | a74b8    | m          | a74b8@zc.com |       1 |
    | 00000000179 | 661ca    | m          | 661ca@zc.com |       1 |
    | 00000000180 | 9413d    | m          | 9413d@zc.com |       1 |
    | 00000000181 | 7d577    | m          | 7d577@zc.com |       1 |
    +-------------+----------+------------+--------------+---------+

    接下里使用EXISTS 来查询数据:

     SELECT * 
     FROM t_emp 
     WHERE EXISTS 
         (SELECT 1 
         FROM t_dept 
         WHERE t_dept.dept_id = t_emp.dept_id) 
     LIMIT 5;

    查询结果:与上面的结果一样。

    +-------------+----------+------------+--------------+---------+
    | emp_id      | emp_name | emp_gender | emp_email    | dept_id |
    +-------------+----------+------------+--------------+---------+
    | 00000000177 | 41d80    | m          | 41d80@zc.com |       1 |
    | 00000000178 | a74b8    | m          | a74b8@zc.com |       1 |
    | 00000000179 | 661ca    | m          | 661ca@zc.com |       1 |
    | 00000000180 | 9413d    | m          | 9413d@zc.com |       1 |
    | 00000000181 | 7d577    | m          | 7d577@zc.com |       1 |
    +-------------+----------+------------+--------------+---------+

    既然IN 和 EXISTS 都可以用来查询数据,那它们两个有什么区别呢?

    SELECT * 
    FROM t_emp 
    WHERE dept_id IN 
        (SELECT dept_id 
        FROM t_dept);
    
    // 这条SQL 语句相当于:
    for SELECT dept_id FROM t_dept
        for SELECT * FROM t_emp WHERE t_emp.dept_id = t_dept.dept_id

    这里虽然我们编写的SQL 语句是主查询员工信息,子查询部门id ,但是MySql 的执行顺序会先执行子查询,再执行主查询,然后获得我们要查询的数据。

     SELECT * 
     FROM t_emp 
     WHERE EXISTS 
         (SELECT 1 
         FROM t_dept 
         WHERE t_dept.dept_id = t_emp.dept_id);
    
    // 这条SQL 语句相当于:     
    for SELECT * FROM t_emp 
        for SELECT * FROM t_dept  WHERE t_dept.dept_id = t_emp.dept_id   
           

    我们可以将EXISTS 语法理解为:将主查询的数据放在子查询中做条件验证,根据结果TRUE 和 FALSE 来决定主查询中的数据是否需要保留。EXISTS 子查询只返回TRUE 或 FALSE ,因此子查询中的SELECT * 可以是SELECT 1 或者其他,MySql 的官方说在实际执行时会忽略SELECT 清单,因此是没有 什么区别的。EXISTS 子查询其实在执行时,MySql 已经对它做了一些优化并不是对每条数据进行对比。

    二、总结

    在实际操作过程中我们要对两张表的dept_id 都设置索引。在一开始我们就讲了一个优化原则即:小表驱动大表,在我们使用IN 进行关联查询时,通过上面IN 操作的执行顺序,我们是先查询部门表再根据部门表查出来的id 信息查询员工信息。我们都知道员工表肯定会有很多的员工信息,但是部门表一般只会有很少的数据信息,我们事先通过查询部门表信息查询员工信息,以小表(t_dept)的查询结果,去驱动大表(t_emp),这种查询方式是效率很高的,也是值得提倡的。

    但是我们使用EXISTS 查询时,首先查询员工表,然后根据部门表的查询条件返回的TRUE 或者 FALSE ,再决定员工表中的信息是否需要保留。这不就是用大的数据表(t_emp) 去驱动小的数据表小的数据表(t_dept)了吗?虽然这种方式也可以查出我们想要的数据,但是这种查询方式是不值得提倡的。

    当t_emp 表中数据多于 t_dept 表中的数据时,这时我们使用IN 优于 EXISTS。当t_dept 表中数据多于 t_emp 表中的数据时(我们这里只是假设),这时我们使用EXISTS 优于 IN。因此是使用IN 还是使用EXISTS 就需要根据我们的需求决定了。但是如果两张表中的数据量差不多时那么是使用IN 还是使用 EXISTS 差别不大。

  • 相关阅读:
    Django 安装步骤
    Django day01 web应用程序 , http协议
    如何让 vue 在 sublime 中变成彩色的
    HTML 14 JS事件
    HTML中常用的颜色词汇
    HTML 13 常用构造函数( 类 )
    sublime 的快捷键大全
    python 46 盒模型 与盒模型布局
    python 46 边界圆角 、a_img_list标签 、伪类选择器
    python 46 css组合选择器 及优先级 、属性选择器
  • 原文地址:https://www.cnblogs.com/fanfan-90/p/13197463.html
Copyright © 2020-2023  润新知