zoukankan      html  css  js  c++  java
  • SQL Server性能调优--优化建议(二)

    序言

    优化建议

      库表的合理设计对项目后期的响应时间和吞吐量起到至关重要的地位,它直接影响到了业务所需处理的sql语句的复杂程度,为提高数据库的性能,更多的把逻辑主外键、级联删除、减少check约束、给null字段添加default值等操作放到了程序端;就如,虽然修改存储过程有时候可以避免发布程序,但过多的逻辑判断也随之带来了性能问题;所以出发点不同取其平衡就好。

      优化sql语句最基本的原则就是将sql语句简单化,将一个复杂的sql语句拆解执行,如图可以看出我们所执行的sql语句都是经过查询优化器分析得到高效的执行计划,那么简单的sql语句很大程度上提高了执行效率。

    1、select

    对于实时性不强的数据可以使用with (nolock),使用强制索指导执行计划。

    select * from Person.Person with (nolock) 
    select * from Person.Person with (index(PK_Person_BusinessEntityID))
    View Code

    避免子查询(先将子查询里面的内容提取出来作为一个临时表,再次join的时候就快了)

    select * from Person.Password where BusinessEntityID in (select BusinessEntityID from Person.Person where FirstName='Ken');
    --替换为
    with tb(BusinessEntityID) as (select BusinessEntityID from Person.Person where FirstName='Ken')
    select * from Person.Password where exists(select 1 from tb where BusinessEntityID=Person.Password.BusinessEntityID);
    View Code

    2、where

    导致index scan或table scan

    select * from tb where like '%value%' -- like 'value%'
    select * from tb where colum1<>0
    select * from tb where colum1=1 or colum2=2 --colum1或colum2没有索引则导致全表扫描
    --尽量使用exists代替in
    select * from tb1 where colum in (select colum from tb2); -- select * from tb1 where exists(select 1 from tb2 where colum=tb1.colum);
    View Code

    在有索引的字段中避免使用函数和表达式,导致索引无法使用

    select * from tb where datediff(mm,'2015-1-1',colum1)=1;
    select * from tb where substring(colum1,1,6)='value';
    View Code

    3、join

    --join连接最好不要超过5个表,有更新的大数据表先放进临时表,然后再join
    select BusinessEntityID,FirstName into #tmptable from Person.Person;
    select * from Person.Password,#tmptable where Person.Password.BusinessEntityID=#tmptable.BusinessEntityID
    drop table #tmptable
    View Code

    4、insert

    --批量插入数据,select into一定比逐条insert快
    insert into tb values(colum1,colum2,colum3),(colum1,colum2,colum3),(colum1,colum2,colum3);
    --文件批处理bulk insert和openrowset
    https://technet.microsoft.com/zh-cn/library/ms188365(v=sql.105).aspx
    View Code

    5、procedure,存储过程优点是执行速度快,因为它是预编译过的,并且执行之后会缓存到plan cache中。

    6、漏洞注入,动态语句参数化查询时不要忘记sp_executesql代替exec

    create proc proc_xxx
    @addressid int,
    @city nvarchar(16)
    as
    begin
        declare @sql nvarchar(1148);
        set @sql='select * from (select *,num=(row_number() over(order by AddressID asc)) from Person.Address where 1=1';
        if(@city<>'')
        begin
            set @sql=@sql+' and City like @city';
        end
        if(@addressid<>0)
        begin
            set @sql=@sql+' and ID=@addressid';
        end
        set @sql=@sql+' ) A where A.num between @sindex and @eindex';
        exec sp_executesql @sql,N'@city nvarchar(64),@addressid int,@sindex int,@eindex int',@city,@addressid,@sindex,@eindex;
    end
    View Code

    索引优化

    1、创建索引的关键在于减少sql语句执行时的逻辑读取次数,逻辑次数读取越少,执行所需的内容和cup时间也越少,则sql语句执行的越快;如果逻辑读取次数过大,返回数据较少则需考虑索引优化。

    set statistics io on
    go
    select * from Production.WorkOrder where WorkOrderID=1
    go
    set statistics io off
    --表 'WorkOrder'。扫描计数 0,逻辑读取 2 次,物理读取 0 次,预读 0 次,lob 逻辑读取 0 次,lob 物理读取 0 次,lob 预读 0 次。
    View Code

    2、分析所缺少的索引,通过语句查询自从上次SQL Server服务重启之后到当前时间为止全部数据库中可能缺少哪些索引。

    select  b.name ,  --数据库名称
            a.statement ,  --缺少索引表的名称
            a.equality_columns ,  --经常用于等值比较的列名,如 ID=value
            inequality_columns ,  --经常用于不等值比较的列名,如 ID>value ID<>value
            included_columns  --建议在索引中涵盖或者包含的列
    from    sys.[dm_db_missing_index_details] a
            join sys.databases b on a.database_id = b.database_id
    View Code

    3、分析索引的使用情况,通过语句查询自从上次SQL Server服务重启之后到当前时间为止数据库中所有索引的使用情况。

    a、seek过少,而scans或update过大,证明索引不被经常使用,而是用于修改和全表扫描,那么就可以考虑删除此索引了;

    b、seek过多,而scans和update也过大,维护索引成本较高,就要考虑权衡利弊了。

    --更新表索引的统计信息
    update statistics tablename with fullscan
    
    select
         db_name() as DBNAME,  --数据库名称
     object_name(a.object_id) as table_name,  --表名称
     coalesce(name,'object with no clustered index') as index_name, --索引名称
     type_desc as index_type,  --索引类型
     user_seeks,  --使用索引查询的次数
     user_scans,  --使用全表扫描的次数
     user_lookups,  --使用书签的次数,使用书签会造成二次IO,考虑是否加入非聚集索引
     user_updates  --索引的更新次数
    from sys.dm_db_index_usage_stats a inner join sys.indexes b
    on a.index_id = b.index_id  and a.object_id = b.object_id
    where database_id = db_id('AdventureWorks2008')
    View Code

    资料

    Sql Server优化之路

  • 相关阅读:
    让mysql查询强制走索引
    【转】起始时间和终止时间,循环输出每天
    【转】31个实用的find命令
    Hive数据倾斜解决办法总结
    网站架构之可扩展性
    网站架构之高可用性
    网站架构之可伸缩性
    kafka中的消费组
    MySQL知识点小结
    [数据挖掘]用户画像
  • 原文地址:https://www.cnblogs.com/cnki/p/11239158.html
Copyright © 2011-2022 走看看