当前位置:   article > 正文

sql优化-把派生表改成子查询,查询速度将变快

使用派生表替代子查询

使用数据库:MYSQL 5.7.27

参考资料:

数据库~Mysql派生表注意的几点~关于百万数据的慢查询问题
https://blog.csdn.net/weixin_34146410/article/details/93984487
子查询:在一个查询中嵌套另一个查询,则另一个查询成为子查询,也叫内部查询
派生表:在FROM子句中使用子查询时,从子查询返回的结果集将用作临时表。 该表称为派生表
当查询的复杂sql数据量大时,把 派生表 改成 子查询, 查询速度将变快
因为派生表不能走索引,子查询可以走索引
 两张表:
ding_talk_employee 钉钉员工表: 总共408条数据
ding_talk_employee_analysis 钉钉员工统计年份分析表: 总共2259条数据
在数据量比较小时: 派生表查询速度比子查询快一倍
派生表sql:
  1. SELECT
  2. t0.department_name,
  3. t0.department_id,
  4. -- 上一年度正式人员
  5. IFNULL(t1.beforeYearNormalCount,0) as beforeYearNormalCount,
  6. -- 当前正式人员
  7. IFNULL(t2.normalCount,0) as normalCount,
  8. -- 较上年新增正式人员数
  9. IFNULL(t2.normalCount,0)-IFNULL(t1.beforeYearNormalCount,0) as normalCompareBeforeYearCount,
  10. -- 试用人员
  11. IFNULL(t3.probationCount,0) as probationCount,
  12. -- 人员折算总计
  13. IFNULL(t4.sumCoefficient,0) as sumCoefficient
  14. from
  15. (
  16. select
  17. MIN(a.department_name) as department_name,
  18. a.department_id,
  19. count(1)
  20. from ding_talk_employee a
  21. where a.department_name !='' -- and dimission_remarks !='不统计'
  22. group by a.department_id ORDER BY department_name
  23. ) as t0
  24. LEFT JOIN
  25. (
  26. -- 上一年度正式人员
  27. SELECT
  28. a.department_id,
  29. count( 1 ) AS beforeYearNormalCount
  30. FROM
  31. ding_talk_employee a
  32. INNER JOIN ding_talk_employee_analysis dtea ON a.userid = dtea.userid
  33. WHERE
  34. dtea.count_year = DATE_ADD('2021-01-01 00:00:00', INTERVAL - 1 YEAR )
  35. AND dtea.employee_status IN ( '3', '5' )
  36. GROUP BY a.department_id
  37. ) AS t1 on t1.department_id=t0.department_id
  38. LEFT JOIN
  39. (
  40. -- 当前正式人员
  41. SELECT
  42. a.department_id,
  43. count( 1 ) AS normalCount
  44. FROM
  45. ding_talk_employee a
  46. INNER JOIN ding_talk_employee_analysis dtea ON a.userid = dtea.userid
  47. WHERE
  48. dtea.count_year = '2021-01-01 00:00:00'
  49. AND dtea.employee_status IN ( '3', '5' )
  50. GROUP BY a.department_id
  51. ) AS t2 on t2.department_id=t0.department_id
  52. LEFT JOIN
  53. (
  54. -- 试用人员
  55. SELECT
  56. a.department_id,
  57. count(1) AS probationCount
  58. FROM
  59. ding_talk_employee a
  60. INNER JOIN ding_talk_employee_analysis dtea ON a.userid = dtea.userid
  61. WHERE
  62. dtea.count_year = '2021-01-01 00:00:00'
  63. AND dtea.employee_status = '2'
  64. GROUP BY a.department_name
  65. ) AS t3 on t3.department_id=t0.department_id
  66. LEFT JOIN
  67. (
  68. SELECT
  69. a.department_id,
  70. SUM(dtea.coefficient) AS sumCoefficient
  71. FROM
  72. ding_talk_employee a
  73. INNER JOIN ding_talk_employee_analysis dtea ON a.userid = dtea.userid
  74. WHERE
  75. dtea.count_year = '2021-01-01 00:00:00'
  76. GROUP BY a.department_id
  77. ) AS t4 on t4.department_id=t0.department_id

不使用缓存的查询时间

派生表查询时间 0.047s

使用 explain 命令查看索引使用情况

总共5个派生表,看索引情况,派生表会自动创建索引

 查看具体耗时步骤:

使用命令:

  1. show profiles (查询刚才执行sql的对应id)
  2. show profile for query 26

派生表转换成子查询后的sql:

  1. SELECT
  2. tu.department_name,
  3. tu.department_id,
  4. -- 上一年度正式人员
  5. tu.beforeYearNormalCount,
  6. -- 当前正式人员
  7. tu.normalCount,
  8. -- 较上年新增正式人员数
  9. IFNULL(tu.normalCount,0)-IFNULL(tu.beforeYearNormalCount,0) as normalCompareBeforeYearCount,
  10. -- 试用人员
  11. tu.probationCount,
  12. -- 人员折算总计
  13. tu.sumCoefficient
  14. FROM (
  15. SELECT
  16. MIN(t0.department_name) as department_name,
  17. t0.department_id,
  18. IFNULL(
  19. (
  20. -- 上一年度正式人员
  21. SELECT
  22. count( 1 ) AS beforeYearNormalCount
  23. FROM
  24. ding_talk_employee a
  25. INNER JOIN ding_talk_employee_analysis dtea ON a.userid = dtea.userid
  26. WHERE
  27. a.department_id=t0.department_id
  28. AND dtea.count_year = DATE_ADD('2021-01-01 00:00:00', INTERVAL - 1 YEAR )
  29. AND dtea.employee_status IN ( '3', '5' )
  30. GROUP BY a.department_id
  31. )
  32. ,0) as beforeYearNormalCount,
  33. IFNULL(
  34. (
  35. -- 当前正式人员
  36. SELECT
  37. count( 1 ) AS normalCount
  38. FROM
  39. ding_talk_employee a
  40. INNER JOIN ding_talk_employee_analysis dtea ON a.userid = dtea.userid
  41. WHERE
  42. a.department_id=t0.department_id
  43. AND dtea.count_year = '2021-01-01 00:00:00'
  44. AND dtea.employee_status IN ( '3', '5' )
  45. GROUP BY a.department_id
  46. )
  47. ,0) as normalCount,
  48. IFNULL(
  49. (
  50. -- 试用人员
  51. SELECT
  52. count(1) AS probationCount
  53. FROM
  54. ding_talk_employee a
  55. INNER JOIN ding_talk_employee_analysis dtea ON a.userid = dtea.userid
  56. WHERE
  57. a.department_id=t0.department_id
  58. AND dtea.count_year = '2021-01-01 00:00:00'
  59. AND dtea.employee_status = '2'
  60. GROUP BY a.department_name
  61. )
  62. ,0) as probationCount,
  63. IFNULL(
  64. (
  65. SELECT
  66. SUM(dtea.coefficient) AS sumCoefficient
  67. FROM
  68. ding_talk_employee a
  69. INNER JOIN ding_talk_employee_analysis dtea ON a.userid = dtea.userid
  70. WHERE
  71. a.department_id=t0.department_id
  72. AND dtea.count_year = '2021-01-01 00:00:00'
  73. GROUP BY a.department_id
  74. )
  75. ,0) as sumCoefficient
  76. FROM
  77. ding_talk_employee t0
  78. WHERE
  79. t0.department_name !='' -- and dimission_remarks !='不统计'
  80. GROUP BY t0.department_id
  81. ORDER BY t0.department_name
  82. ) as tu

 

 使用子查询的查询时间0.068s

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/在线问答5/article/detail/792985
推荐阅读
相关标签
  

闽ICP备14008679号