用户名:
密 码: 记住
您当前的位置:首页 > 网络编程 > sqlserver教程

通往性能优化的JOIN方法说明

时间:2014-11-30  来源:互联网  作者:佚名

【引自RicCC的博客】前言

看到很多朋友对数据库的理解、认识还是没有突破一个瓶颈,而这个瓶颈往往只是一层窗纸,越过了你将看到一个新世界。

04、05年做项目的时候,用SQL Server 2000,核心表(大部分使用频繁的关键功能每次都要用到)达到了800万数据量,很早以前查过一些相关表,有的达到了3000多万,磁盘使用的光纤盘,100G空间,每周必须备份转移数据,否则100G空间一周会满掉,这个系统几年来,目前仍然保持非常良好的性能。还听说过朋友的SQL Server 2000数据库工作在几十TB的环境下,高并发量,对这种级别的驾驭能力我还是差的很遥远。

想当年,也是一提SQL Server,就觉得它的性能没法跟Oracle相比,一提到大数据处理就想到Oracle。自己一路走来,在本地blog上记录了很多优化方面的post,对的错的都有,没有时间系列的整理出来,这篇文章将join方法的概念稍微整理在一起,给大家个参考。通过查资料了解里面提到的各种概念,在实际中不断验证总结,完全可以对数据库一步步深入理解下去的。

我只对SQL Server 2000比较了解,但这并不阻碍我在Oracle、MySql进行SQL调优、产品架构,因为在数据库理论原理上,各大数据库基本出入不大,对数据库的深入理解,也不会影响你架构设计思想变坏,相反给你带来的是更深层次的思考。

关于执行计划的说明

在SQL Server查询分析器的Query菜单中选择Show Execution Plan,运行SQL查询语句,在结果窗口中有Grid、Execution Plan、Messages三个Tab。看图形形式的执行计划,顺序是从右到左,这也是执行的顺序。执行计划中的每一个图标表示一个操作,每一个操作都会有一个或多个输入,也会有一个或多个输出。输入和输出,有可能是一个物理数据表、索引数据结构,或者是执行过程中的一些中间结果集/数据结构。鼠标移动到图标上,会显示这个操作的具体信息,例如逻辑和物理操作名称、记录的数量和大小、I/O成本、CPU成本、操作的具体表达式(参数Argument)。鼠标移动到连接箭头上,会显示箭头起始端的操作输出结果集的记录数、记录的大小,一般情况下可以将这个输出结果集理解为箭头结束端的输入。

另外关于执行计划的一些补充说明:1. 执行计划中显示的信息,都是一个“评估”的结果,不是100%准确的信息,例如记录数量是取自统计信息,I/O成本、CPU成本来自执行计划生成过程中基于统计信息等得出的评估结果。2. 执行计划不一定准确,一方面受SQL Server维护的统计信息准确性的影响,另一方面SQL语句编译时刻与执行时刻的环境(内存使用状况、CPU状况等)可能会不一样。

关于统计信息、I/O成本和CPU成本的评估、SQL语句的编译和执行过程,这里不再深入。另外尽管执行计划不一定准确,但它仍是SQL语句分析最重要的依据,因为你可以理解为,绝大部分情况下,SQL Server是以这种方式来执行的。

JOIN方法说明

数据库中,象tableA inner join tableB、tableA left out join tableB这样的SQL语句是如何执行join操作的?就是说SQL Server使用什么算法实现两个表数据的join操作?

SQL Server 2000有三种方式:nested loop、merge、hash。Oracle也是使用这三种方式,不过Oracle选择使用nested loop的条件跟SQL Server有点差别,内存管理机制跟SQL Server不一样,因此查看执行计划,Oracle中nested loop运用非常多,而merge和hash方式相对较少,SQL Server中,merge跟hash方式则是非常普遍。

以SQL Server 2000为例对这三种方式进行说明,穿插在里面讲解执行计划的一些初级使用。

1. nested loop join

1.1 示例SQL

select ... from tableA inner join tableB on tableA.col1=tableB.col1 where tableA.col2=? and tableB.col2=?tableA中没有建立任何索引,tableB中在col1上有建立一个主键(聚集索引)。

1.2 算法伪代码描述

foreach rowA in tableA where tableA.col2=?

{

search rowsB from tableB where tableB.col1=rowA.col1 and tableB.col2=? ;

if(rowsB.Count<=0)

discard rowA ;

else

output rowA and rowsB ;

}

join操作有两个输入,上面例子中tableA是outer input,用于外层循环;tableB是inner input,用于循环内部。下面针对执行计划描述一下SQL Server完成这个操作的具体步骤。

1.3 查看执行计划方法

移到文章最前面。

1.4 执行步骤

下面是示例SQL的执行计划图。nested loop操作的右边,位于上面的是outer input,位于下面的是inner input。你不能够根据join中哪个表出现在前面来确定outer input和inner input关系,而必须从执行计划中来确定,因为SQL Server会自动选择哪个作为inner input。

图1

a) 对tableA执行Table Scan操作。这个操作的输入是tableA表中的数据,这些数据位于磁盘上,操作过程中被加载到内存;输出是符合条件的记录集,将作为b)的outer input。在这个操作中,tableA.col1=?的条件会被使用。

b) 执行上面伪代码描述的nested loop操作。对a)中的每个输出记录,执行步骤c)。

c) 对tableB执行Clustered Index Seek操作。这个操作是在nested loop循环里面执行的,输入是tableB表的聚集索引数据。它使用tableB.col1=rowA.col1和tableB.col2=?这两个条件,从tableB的聚集索引中选择符合条件的结果。

d) 构造返回结果集。从nested loop的输出中,整理出select中指定的字段,构造最终输出结果集。

共3页: 1 下一页

【内容导航】

123下一页

来顶一下
返回首页
返回首页
推荐资讯
从零开始学ASP.NET-基础篇第1/7页 从零开始学ASP.NET-基础篇第1/7页第一天 学习目的: 掌握最基本的Label、TextBox、Button控件
ASP.NET入门数据篇 ASP.NET入门数据篇对于网站编程的初学者来说,总是会上网找些源码来看,但久而
相关文章
    无相关信息
栏目更新
栏目热门