永远用小的结果集驱动大的结果集

永远用小的结果集驱动大的结果集

转载自:公司内  数据工程师:

 永远用小的结果集驱动大的结果集

很多人喜欢在优化 SQL 的时候使用小表驱动大表,个人认为这不太严谨。为什么?因为大表经过 WHERE 条件过滤之后返回的结果集并不一定就比小表所返回的大,也许更小。在这种情况下如果仍然采用小表驱动大表,就会得到相反的性能效果。 

其实这也非常容易理解,在MySQL中,只有 Nested Loop 一种 Join 方式,也就是说MySQL的 Join 都是通过嵌套循环来实现的。驱动结果集越大,所需要循环就越多,那么被驱动表的访问次数自然也就越多,而每次访问被驱动表,即使需要的逻辑 IO 很少,循环次数多了,总量也不可能小,而且每次循环都不能避免消耗CPU,所以 CPU 运算量也会跟着增加。如果仅仅以表的大小来作为驱动表的判断依据,假若小表过滤后所剩下的结果集比大表多很多,结果就会在嵌套循环中带来更多的循环次数,反之,所需要的循环次数就会更少,总体 IO 量和 CPU 运算量也会更少。在非 Nested Loop  的 Join  算法中,如 Oracle  中的 Hash  Join,小结果集驱动大的结果集同样是最优的选择。 

所以,在优化 Join Query 的时候,最基本的原则就是“小结果集驱动大结果集”,通过这个原则来减少嵌套循环中的循环次数,以减少 IO总量及CPU运算的次数。 

SELECT
  pproductpr0_.p_product_prop_id AS col_0_0_,
  pproductpr0_.p_product_prop_code AS col_1_0_,
  pproductpr0_.p_product_prop_name AS col_2_0_,
  CASE WHEN pproductpr0_.p_product_prop_val IS NULL THEN ” ELSE pproductpr0_.p_product_prop_val END AS col_3_0_,
  pproductpr0_.p_product_prop_order AS col_4_0_,
  (SELECT
      bdic4_.b_dic_code
    FROM b_dic bdic4_
    WHERE bdic4_.b_dic_id = pproductpr0_.p_product_prop_must) AS col_5_0_,
  pproductpr0_.p_product_prop_status AS col_6_0_,
  (SELECT
      bdic5_.b_dic_code
    FROM b_dic bdic5_
    WHERE bdic5_.b_dic_id = pproductpr0_.p_product_prop_display) AS col_7_0_,
  pproductpr0_.p_product_prop_source AS col_8_0_,
  pproductpr0_.p_product_prop_int_code AS col_9_0_,
  pproduct3_.p_product_id AS col_10_0_,
  pproductpr0_.p_product_prop_default_value AS col_11_0_,
  (SELECT
      bdic6_.b_dic_code
    FROM b_dic bdic6_
    WHERE bdic6_.b_dic_id = pproductpr0_.p_product_prop_available) AS col_12_0_,
  (SELECT
      bdic7_.b_dic_code
    FROM b_dic bdic7_
    WHERE bdic7_.b_dic_id = pproductpr0_.p_product_prop_width) AS col_13_0_,
  (SELECT
      bdic8_.b_dic_code
    FROM b_dic bdic8_
    WHERE bdic8_.b_dic_id = pproductpr0_.p_product_prop_valid_type) AS col_14_0_,
  pproductty2_.p_ptp_classify_id AS col_15_0_,
  pproductty1_.p_ptype_prop_id AS col_16_0_,
  (SELECT
      bdic9_.b_dic_code
    FROM b_dic bdic9_
    WHERE bdic9_.b_dic_id = pproductpr0_.p_product_prop_source_type) AS col_17_0_,
  pproductpr0_.p_product_display_format AS col_18_0_,
  pproductpr0_.p_product_value_field AS col_19_0_,
  pproductpr0_.p_product_text_field AS col_20_0_,
  pproductpr0_.p_product_min_length AS col_21_0_,
  pproductpr0_.p_product_max_length AS col_22_0_,
  pproductpr0_.p_product_event_source AS col_23_0_,
  pproductpr0_.p_product_prop_prop_name AS col_24_0_,
  pproductpr0_.p_product_prop_create_on AS col_25_0_,
  pproductpr0_.p_product_prop_create_by AS col_26_0_,
  pproductpr0_.p_product_prop_update_on AS col_27_0_,
  pproductpr0_.p_product_prop_update_by AS col_28_0_
FROM p_product_prop pproductpr0_
  LEFT OUTER JOIN p_product_type_prop pproductty1_
    ON pproductpr0_.p_ptype_prop_id = pproductty1_.p_ptype_prop_id
  LEFT OUTER JOIN p_product_type_prop_classify pproductty2_
    ON pproductty1_.p_ptp_classify_id = pproductty2_.p_ptp_classify_id
  LEFT OUTER JOIN p_product pproduct3_
    ON pproductpr0_.p_product_id = pproduct3_.p_product_id
WHERE  pproductpr0_.p_product_id = ‘C07C25F3621A4B509E9DCE111812B7BA’
AND EXISTS(
  SELECT pproductty2_.p_ptp_classify_id
  FROM  p_product_type_prop_classify pproductty2_
  WHERE  pproductty1_.p_ptp_classify_id = pproductty2_.p_ptp_classify_id
  AND pproductty2_.p_ptp_classify_id = ‘8a8a94e55162a9db015162b123470065’)
ORDER BY pproductty1_.p_ptype_prop_order;

p_product_prop经过pproductpr0_.p_product_id = ‘C07C25F3621A4B509E9DCE111812B7BA’
过滤之后就是个小的结果集

 再EXISTS的时候,效率也很高

 最终要的是能用上pproductpr0_.p_product_id的单键索引

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/109088.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • java integer的范围_java integer的取值范围是什么?

    java integer的范围_java integer的取值范围是什么?JavaInteger取值范围Integer类取值和int类型取值一致,取值范围是从-2147483648至2147483647,包括-2147483648和2147483647。但是对于Integer类,java为了提高效率,初始化了-128–127之间的整数对象,因此Integer类取值-128–127的时候效率最高。测试:publicclassIntegertest…

    2025年6月28日
    5
  • 我的 Java 自学之路[通俗易懂]

    我的 Java 自学之路[通俗易懂]其实在转正之后我就想抽个时间好好的梳理一下我的Java上车之路,但是一直拖到现在,因为有学弟问到,所以也就给了我动力。毕竟答应了人家的事要做到。首先要有相应的背景介绍,不然说个毛线啊,大家不在同一水平,不好参考借鉴。我呢,学校很牛逼,是一所刚过线的二本,自身的成绩在班里也就第8名左右吧(一共60个人),在大二的时候学校开设了Java这门课,我的期末考试…

    2022年7月7日
    21
  • chip seq实验原理及步骤_思科真机实验环境搭建

    chip seq实验原理及步骤_思科真机实验环境搭建实验内容通过实验环境学习了解SR-PCE。xrv_7作为PCE,计算PE1到PE2的路径。网络中IP设置,metric值与之前的实验一致。拓扑图配置流程:配置SRGB在IGP(is-is)中使能segmentrouting和NodeID修改IGP和TE的链路metric配置PCE我们这次主要关注配置PCE的过程。前面的配置可以参考:SR-TEPolicy(思科)—-explicitpath实验SR-TEPolicy(思科)—-dynamicpath实验P

    2025年9月29日
    1
  • Java的定时器_JAVA定时任务

    Java的定时器_JAVA定时任务总结一下我使用过的4种类型的定时器:@Scheduled注解、quartz、newTimer().schedule、使用线程控制。1.@Scheduled注解@Scheduled注解是最简单的方式,只需要启用定时器,在方法上添加注解即可。在spring配置中加入:<!–启用注解定时器–> <task:annotation-driven/>…

    2025年12月9日
    4
  • cmd 盘符切换[通俗易懂]

    cmd 盘符切换[通俗易懂] pushd D:\Myeclipse8.5

    2022年10月3日
    2
  • 最常用Python开源框架有哪些?

    最常用Python开源框架有哪些?

    2021年10月11日
    91

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号