zoukankan      html  css  js  c++  java
  • T-SQL的10个好习惯

    有关T-SQL的10个好习惯 

    1.在生产环境中不要出现Select *

         这一点我想大家已经是比较熟知了,这样的错误相信会犯的人不会太多。但我这里还是要说一下。

         不使用Select *的原因主要不是坊间所流传的将*解析成具体的列需要产生消耗,这点消耗在我看来完全可以忽略不计。更主要的原因来自以下两点:

    •      扩展方面的问题
    •      造成额外的书签查找或是由查找变为扫描

         扩展方面的问题是当表中添加一个列时,Select *会把这一列也囊括进去,从而造成上面的第二种问题。

         而额外的IO这点显而易见,当查找不需要的列时自然会产生不必要的IO,下面我们通过一个非常简单的例子来比较这两种差别,如图1所示。

        1

        图1.*带来的不必要的IO

    2.声明变量时指定长度

        这一点有时候会被人疏忽,因为对于T-SQL来说,如果对于变量不指定长度,则默认的长度会是1.考虑下面这个例子,如图2所示。

        2

        图2.不指定变量长度有可能导致丢失数据

    3.使用合适的数据类型

        合适的数据类型首先是从性能角度考虑,关于这一点,我写过一篇文章详细的介绍过,有兴趣可以阅读:对于表列数据类型选择的一点思考,这里我就不再细说了

       不要使用字符串类型存储日期数据,这一点也需要强调一些,有时候你可能需要定义自己的日期格式,但这样做非常不好,不仅是性能上不好,并且内置的日期时间函数也不能用了。

    4.使用Schema前缀来选择表

        解析对象的时候需要更多的步骤,而指定Schema.Table这种方式就避免了这种无谓的解析。

        不仅如此,如果不指定Schema容易造成混淆,有时会报错。

        还有一点是,Schema使用的混乱有可能导致更多的执行计划缓存,换句话说,就是同样一份执行计划被多次缓存,让我们来看图3的例子。

        3

        图3.不同的schema选择不同导致同样的查询被多次缓存

    5.命名规范很重要

        推荐使用实体对象+操作这种方式,比如Customer_Update这种方式。在一个大型一点的数据库会存在很多存储过程,不同的命名方式使得找到需要的存储过程变得很不方便。因此有可能造成另一种问题,就是重复创建存储过程,比如上面这个例子,有可能命名规范不统一的情况下又创建了一个叫UpdateCustomer的存储过程。

    6.插入大量数据时,尽量不要使用循环,可以使用CTE,如果要使用循环,也放到一个事务中

        这点其实显而易见。SQL Server是隐式事务提交的,所以对于每一个循环中的INSERT,都会作为一个事务提交。这种效率可想而知,但如果将1000条语句放到一个事务中提交,效率无疑会提升不少。

        打个比方,去银行存款,是一次存1000效率高,还是存10次100?下面,根据吉日的要求,补个例子,见代码1.

    CREATE TABLE dbo.TestInsert
    (
    	Number INT PRIMARY KEY
    );
    --循环插入,不给力,我的笔记本45秒
    DECLARE @index INT;
    SET @index = 1;
    
    WHILE @index <= 100000
    BEGIN
    	INSERT dbo.TestInsert(Number) VALUES( @index);
    	SET @index = @index + 1;
    END
    
    
    
    --放到一个事务中循环,略好,但也不是最好,我的笔记本1秒
    BEGIN TRAN
    DECLARE @index INT;
    SET @index = 1;
    
    WHILE @index <= 100000
    BEGIN
    	INSERT dbo.TestInsert(Number) VALUES( @index);
    	SET @index = @index + 1;
    END
    
    COMMIT
    
    --批量插入,10W行,显示0秒,有兴趣的同学改成100W行进行测试
    INSERT dbo.TestInsert(Number)
    	SELECT TOP (100000) rn = ROW_NUMBER() OVER
    		(ORDER BY c1.[object_id])
    		FROM sys.columns AS c1
    		CROSS JOIN sys.columns AS c2
    		CROSS JOIN sys.columns AS c3
    		ORDER BY c1.[object_id];
    
    
    --CTE方式,和上面那种方式大同小异,也是批量插入,比如:
    WITH cte AS(
    	SELECT TOP (100000) rn = ROW_NUMBER() OVER
    		(ORDER BY c1.[object_id])
    		FROM sys.columns AS c1
    		CROSS JOIN sys.columns AS c2
    		CROSS JOIN sys.columns AS c3
    		ORDER BY c1.[object_id]
    )
    INSERT dbo.TestInsert(Number) SELECT rn FROM cte

        代码1.几种插入方式的比较

    7.where条件之后尽量减少使用函数或数据类型转换

       换句话说,WHERE条件之后尽量可以使用可以嗅探参数的方式,比如说尽量少用变量,尽量少用函数,下面我们通过一个简单的例子来看这之间的差别。如图4所示。

       4

        图4.在Where中使用不可嗅探的参数导致的索引查找

        对于另外一些情况来说,尽量不要让参数进行类型转换,再看一个简单的例子,我们可以看出在Where中使用隐式转换代价巨大。如图5所示。

        5

        图5.隐式转换带来的性能问题

    8.不要使用旧的连接方式,比如(from x,y,z)

        可能导致效率低下的笛卡尔积,当你看到下面这个图标时,说明查询分析器无法根据统计信息估计表中的数据结构,所以无法使用Loop join,merge Join和Hash Join中的一种,而是使用效率地下的笛卡尔积。

    >   这里我再补充一点,我说得是“可能”导致,因为上面这个查询可能作为中间结果或是子查询,当你忘写了where条件时,会是笛卡尔积。你在最终结果中再用where过滤,可能得到的结果一模一样,但是中间的过程却大不相同

        image

        所以,尽量使用Inner join的方式替代from x,y,z这种方式。

    9.使用游标时,加上只读只进选项

        首先,我的观点是:游标是邪恶的,尽量少用。但是如果一定要用的话,请记住,默认设置游标是可进可退的,如果你仅仅设置了

    declare c cursor
    
        for

        这样的形式,那么这种游标要慢于下面这种方式。

         
       

     declare c cursor
    
        local static read_only forward_only
    
        for

        所以,在游标只读只进的情况下,加上上面代码所示的选项。

    10.有关Order一些要注意的事情

        首先,要注意,不要使用Order by+数字的形式,比如图6这种。

        6

        图6.Order By序号

        当表结构或者Select之后的列变化时,这种方式会引起麻烦,所以老老实实写上列名。

        还有一种情况是,对于带有子查询和CTE的查询,子查询有序并不代表整个查询有序,除非显式指定了Order By,让我们来看图7。

        7

        图7.虽然在CTE中中有序,但显式指定Order By,则不能保证结果的顺序

     
     
    分类: T-SQL
  • 相关阅读:
    Educational Codeforces Round 20 D. Magazine Ad
    Educational Codeforces Round 20 C. Maximal GCD
    紫书第三章训练2 暴力集
    Educational Codeforces Round 20 B. Distances to Zero
    Educational Codeforces Round 20 A. Maximal Binary Matrix
    紫书第三章训练1 D
    紫书第一章训练1 D -Message Decoding
    HAZU校赛 Problem K: Deadline
    Mutual Training for Wannafly Union #8 D
    紫书第三章训练1 E
  • 原文地址:https://www.cnblogs.com/Leo_wl/p/3293003.html
Copyright © 2011-2022 走看看