博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SQL Server nested loop join 效率试验
阅读量:4315 次
发布时间:2019-06-06

本文共 2330 字,大约阅读时间需要 7 分钟。

自:

从很多网页上都看到,SQL Server有三种Join的算法, nested loop join, merge join, hash join. 其中最常用的就是nested loop join.

在介绍nested loop join的很多文章里,都提到如果两个表做nested loop join,取行数较小的表作为外循环表,行数较多的表作为内循环表, join的效率会比较高.
其中之一的原因是如果内循环表做join的列上有合适的索引的话,那么外循环的每一条输入数据可以做索引的seek,这样就不会把整个的内循环表读一遍,尤其是内循环表比较大的话,节省的成本更高. 但是如果内外循环表都没有合适的索引,这样做join,为什么效率也比较高呢?
举个例子,外循环表有10行数据,内循环表有1000行数据,按照nested loop join 的算法,外循环表中取一条,和内循环表的所有数据匹配一遍,输出匹配的数据行. 这样就是要进行10*1000=10000次的匹配; 如果反过来,外循环1000行,内循环10行,那么外循环表中取一条数据,内循环表中遍历10行数据,总计也是1000*10=10000次. 粗看来都一样啊..为什么都说外循环表小的话,效率高呢?  做个试验看看吧.

  1. use tempdb
  2. go
  3. --创建两个表,测试nested loop join的效率
  4. CREATE TABLE TempA (string VARCHAR(1000))
  5. go
  6. CREATE TABLE TempB (string VARCHAR(1000))
  7. go
  8. --插入数据, 让表TempA中的数据刚好存在1页里
  9. INSERT INTO TempA SELECT REPLICATE('a' , 1000)
  10. INSERT INTO TempA SELECT REPLICATE('b' , 1000)
  11. INSERT INTO TempA SELECT REPLICATE('c' , 1000)
  12. INSERT INTO TempA SELECT REPLICATE('d' , 1000)
  13. INSERT INTO TempA SELECT REPLICATE('e' , 1000)
  14. INSERT INTO TempA SELECT REPLICATE('f' , 1000)
  15. INSERT INTO TempA SELECT REPLICATE('g' , 1000)
  16.  
  17. --往TempB中插入数据,让TempB的数据是TempA的100倍
  18. insert into TempB select * from TempA
  19. go 100
  20. --检验一下表TempA 和 TempB的大小
  21. set statistics io on
  22. select * from TempA
  23. select * from TempB
  24. --返回的结果如下:
  25. /*
  26. Table'TempA'. Scan count 1, logical reads 1
  27. Table'TempB'. Scan count 1, logical reads 100
  28. */
  29. --由此可以看出表TempA有7行,存储在1个页; TempB有700行,存储在100个页里.
  30.  
  31. --执行以下查询,将TempA作为外循环表,TempB作为内循环表,看看执行的成本如何
  32. SELECT *FROM TempA a INNER LOOP JOIN TempB b
  33. ONa.string = b.string
    OPTION (FORCE order)
  34. /*
  35. Table'TempB'. Scan count 1, logical reads 700
  36. Table'TempA'. Scan count 1, logical reads 1
  37. */
从结果可以看出从TempA读了1个页,从TempB读了700个页,合计701个逻辑读, 也就是说外循环的表,做一次全表读,有多少页就有多少逻辑读; 内循环的表,对应外循环表的每1条记录,都要读一次全表读,即7乘以100,700个逻辑读.
如果按照这个规律,调换内外循环表的位置,得到的逻辑读应该是 TempB的一次全表读, 100个逻辑读加上700行乘以TempA的全表读(1页),就是700个逻辑读,合计是800个逻辑读.
试验一下看看结果:

 

  1. --对调一下join的顺序,再看看执行成本:
  2. SELECT *FROM tempb b INNER LOOP JOIN tempa a
  3. ONa.string = b.string
    OPTION(FORCE ORDER)
  4. /*
  5. Table'TempA'. Scan count 1, logical reads 700
  6. Table'TempB'. Scan count 1, logical reads 100
  7. */
果不其然,和预计的一样.

所以在这种假定的情况下,外循环表较小的话,join的成本更低.

实验的表结构比较特殊,如果往一般情况推演一下,可以做出这样的假设:
假设表X有a页,平均每页有b行,表Y有c页,平均每页有d行.
则以表X为外循环,表Y为内循环,则nested loop join的成本是 a+(a*b*c), 而已表Y为外循环,表X为内循环,则nested loop join的成本是 c+(c*d*a)
比较两种方式的成本大小可以将两个代数式相减,再根据abcd不同的情况的出相应的结论.希望各位可以自行推理一番..

转载于:https://www.cnblogs.com/dragon2017/p/9351920.html

你可能感兴趣的文章
POJ 3621
查看>>
PHP ajax实现数组返回
查看>>
java web 自定义filter
查看>>
J.U.C Atomic(二)基本类型原子操作
查看>>
POJ---2945 Find the Clones[字典树-简单题(多例输入注意删除)]
查看>>
[Luogu4550] 收集邮票
查看>>
Python-循环
查看>>
(转)最大子序列和问题 看着貌似不错
查看>>
thinkphp3.2 链接数据库测试
查看>>
项目的上线流程是怎样的?
查看>>
Linux通配符
查看>>
ES6 Iterator
查看>>
Apache2.4开启GZIP功能
查看>>
远程桌面关闭重启电脑的方法
查看>>
第三章 熟悉常用的HDFS操作
查看>>
filter:expression(document.execCommand("BackgroundImageCache",false,true) 转
查看>>
Java - 30 Java 网络编程
查看>>
shiro中的filterChainDefinitions
查看>>
瑞柏匡丞教你如何和程序员一起愉快的玩耍
查看>>
【单调队列】Vijos P1771 瑞士轮 (NOIP2011普及组第三题)
查看>>