高效SQL查询之索引(I)
大型系统的生产环境,一般情况下,我们评价一条查询是否有效率,更多的是关注逻辑 IO( 至于为什么,回头补一篇 ) 。我们常说,“要建彪悍的索引”、“要写高效的 SQL ”,其实最终目的就是在相同结果集情况下,尽可能减少逻辑 IO 。
1.1 where 条件的列上都得有统计信息。
没统计信息 SQLServer 就无法估算不同查询计划开销优劣,而只能采用最稳妥的 Scan (不管是 table scan 还是 clustered index scan )。一般情况下我们不会犯这种错误—— where 条件里不使用非索引列是个常识。索引上的统计信息是无法删除的。
1.2 尽量不使用不等于( != )或者 NOT 逻辑运算符。
这条规则被广为传颂,原因据联机文档和百敬同学的书讲,也是 SQLServer 无法评估不同查询计划开销的优劣。但是 SqlServer2k5 聪明了很多,试验发现尽管用了 != 或者 not ,查询还是会被优化。如下:
create table tb1
(
col1 int identity ( 1, 1) primary key ,
col2 int not null,
col3 varchar ( 64) not null
)
create index ix_tb1_col2 on tb1
(
col2
)
create index ix_tb1_col3 on tb1
(
col3
)
declare @f int
set @f = 0
while @f < 9999
begin
insert into tb1 ( col2, col3) values ( 1, 'ssdd' )
set @f = @f + 1
end
insert into tb1 ( col2, col3) values ( 0, 'aadddd' )
insert into tb1 ( col2, col3) values ( 2, 'bbddd' )
insert into tb1 ( col2, col3) values ( 3, 'bbaaddddddaa' )
通过上述代码,各位可以看到数据分布。 col2 值为 1 的有 9999 条; col2 值为 0 、 2 、 3 的分别有 1 条。
按照本条规则, != 和 NOT 带来的应该是个 scan 操作,但实际情况是:
SQL2k5 很聪明,它依据统计信息分析得出来,应该采用 index seek 而不是 index scan 。(稍微解释解释 index seek 和 index scan :索引是一颗 B 树, index seek 是查找从 B 树的根节点开始,一级一级找到目标行。 index scan 则是从左到右,把整个 B 树遍历一遍。假设唯一的目标行位于索引树(假设是非聚集索引,树深度 2 ,叶节点占用 k 页物理存储)最右的叶节点上(如上例)。
相关文档:
方法(1)
SELECT stuff((select ','+ltrim(ColumnName) from #A for xml path('')
),1,1,'')
/*
102,103,104,105
*/
方法(2)
DECLARE @s NVARCHAR(1000)='';
SELECT @s+=ColumnName+',' from #A;
SELECT @s; ......
今天在配置数据库发布和分发时总是报出现 18483 错误
提示说:错误 18483:未能连接到服务器 "XXX",因为 'distributor_admin'未在该服务器上定义为远程登陆。
我的发布和分发是同一个服务器,"XXX" 为我的机器名,分发数据库是默认的名称,而我在另外一台机器上做时就正常。
1、设置共享复制目录:
......
本文演示了 SQL Server 2008 分区表实例;
1. 创建测试数据库 ;
2. 创建分区函数;
3. 创建分区架构;
4. 创建分区表;
5. 创建分区索引 ;
6. 分区切换 ;
7. 查询哪些表使用了分区表;
-- 作成者 leno
-- 日期: 2009-06-06 23:50:01.700
-- ......
先站在应用程序的角度说说它们的不同。
1、 直接拼 SQL
就像大家了解的那样,直接拼 SQL 带来了 SQL 注入攻击,带来了拼时些许的性能损失,但是拼不用添加 SqlParameter ,会少写很多代码——很多人喜欢直接拼,也许就因为这点。这种做法会把你拼好的 SQL 原样直接发送到 DB 服务器去执行。(注意类似 &rdquo ......
我们先看 NestedLoop 和 MergeJoin 的算法(以下为引用,见 RicCC 的《 通往性能优化的天堂 - 地狱 JOIN 方法说明 》 ):
==================================
NestedLoop:
foreach rowA in tableA where tableA.col2=?
{
search rowsB from tableB where tableB.c ......