当前位置: 首页 > 科技观察

常用SQLServer规范的集合?看这里~

时间:2023-03-15 19:26:54 科技观察

常用字段类型选择1.字符类型推荐使用varchar/nvarchar数据类型2.金额货币推荐使用货币数据类型3.科学计数法推荐使用数字数据类型4.自增识别建议使用bigint数据类型(数据量大,不能使用int类型,转换起来会很麻烦)5.时间类型建议使用datetime数据类型6.禁止使用text、ntext、image旧数据类型7.禁止使用xml数据类型,varchar(max),nvarchar(max)约束和索引每张表必须有主键每张表必须有主键,用于强制实体完整性。单表只能有一个主键(不允许有null和重复数据)尽量使用单字段主键,不允许使用外键。外键增加了表结构更改和数据迁移的复杂性。外键会影响插入和更新的性能。需要检查主键和外键约束。数据完整性由程序控制。新加表的NULL属性,所有字段禁止NULL(为什么新表不允许NULL?允许NULL值会增加应用的复杂度,必须添加特定的逻辑代码,防止各种意想不到的bug。三-值逻辑,所有等号(“=”)查询都要加上isnull判断。Null=Null,Null!=Null,not(Null=Null),not(Null!=Null)都是未知的,不是真的)例如:如果表中的数据如图所示:你要找除了所有name等于aa的数据,然后你无意中用了SELECT*FROMNULLTESTWHERENAME<>'aa',发现和预期的不一样。其实它只找到了name=bb,没有找到name=NULL我们如何找到除了name等于aa的所有数据呢?我们只能使用ISNULL函数SELECT*FROMNULLTESTWHEREISNULL(NAME,1)<>'aa'但是你可能不知道ISNULL会造成严重的性能瓶颈,所以很多情况下最好限制用户的输入在应用层确保用户在查询前输入有效数据。旧表新增字段需要允许为NULL(避免全表数据更新,长期锁造成阻塞)(这里主要是考虑对之前表的改造)索引设计准则应该为频繁创建索引WHERE子句中使用的列应该在连接表中经常使用的列上建立索引,应该在ORDERBY子句中经常使用的列上建立索引。小表(那些只使用几页的)不应该被索引,因为全表扫描操作可能比单表索引的数量不超过6。不要为选择性低的字段创建单列索引.充分利用独特的约束。索引包含不超过5个字段(包括包含列)。不要为选择性低的字段创建单列索引。索引SQLSERVER对索引字段的选择性有要求。选择性太低,SQLSERVER会放弃使用不适合建索引的字段:gender,0/1,TRUE/FALSE适合建索引的字段:ORDERID,UID等,充分利用它们唯一索引唯一索引为SQLServer提供信息以确保列中绝对没有重复值。当查询分析器通过唯一索引找到一条记录时,会立即退出,不会继续查找索引。表索引数不超过6个。不超过6个(这个规则是携程DBA经过实验才制定的...)索引加快了查询速度,但是会影响写入性能。一个表的索引应该结合所有与该表相关的SQL来创建。尽可能结合综合指数的原则是过滤性越好,前沿越高。索引太多。会增加编译时间,也会影响数据库选择***执行计划SQL查询禁止在数据库中进行复杂操作禁止使用SELECT*禁止对索引列使用函数或计算禁止使用游标禁止使用triggers禁止在查询中指定索引变量/parameters/关联的字段类型必须与字段类型一致。参数化查询限制了JOIN的数量。限制SQL语句的长度和IN子句的数量。尽量避免大事务操作关闭返回的行数信息。除非必要,否则SELECT语句必须加上NOLOCK。UNIONALL代替UNION查询大量数据使用分页或TOP递归查询级别限制NOTEXISTS代替NOTIN临时表和表变量使用局部变量选择适度的执行计划尽量避免使用OR运算符增加事务异常处理机制输出列使用两阶段命名格式禁止在数据库中进行复杂计算XML解析字符串相似度比较字符串搜索(Charindex)复杂计算在终端中完成禁止使用SELECT*减少内存消耗和网络带宽给查询优化器机会从索引中读取需要的列表,当结构发生变化时很容易导致查询错误。禁止在索引列上使用函数或计算。在where子句中,如果索引是函数的一部分,优化器将不再使用索引而使用全表扫描。假设字段Col1上有索引,以下场景将无法使用索引:ABS[Col1]=1[Col1]+1>9再举个例子说明如上查询,将不能在O_OrderProcess表上使用PrintTime索引,所以我们使用如下应用所示的查询SQL,禁止在索引列上使用函数或计算。假设在字段Col1上建立了索引,那么索引可用于以下场景:[Col1]=3.14[Col1]>100[Col1]BETWEEN0AND99[Col1]LIKE'abc%'[Col1]IN(2,3,5,7)LIKE查询的索引问题1.[Col1]like"abc%"--indexseek这个用到了索引查询2.[Col1]like"%abc%"--indexscan而这个不是索引查询没有用到3.[col1]like"%abc"--indexscan这个也没有用到索引查询从上面三个例子我觉得大家应该明白了,***不要在LIKE条件前使用模糊匹配,否则没有使用索引查询。关系数据库禁止使用游标。关系数据库适用于集合操作,即集合操作是对WHERE子句和选择的列所确定的结果集进行操作。游标提供了一种非集合的操作方式。一般来说,游标实现的功能往往等同于客户端的一个循环实现的功能。游标是将结果集放在服务器内存中,通过循环的方式对记录进行一条一条的处理,消耗了大量的数据库资源(尤其是内存和锁资源)。(另外,游标真的很复杂,不好用,尽量少用)禁止使用触发器触发器对应用程序是不透明的(应用程序层不知道触发器什么时候会被触发,也没有发生,感觉莫名其妙。。。)禁止在查询中指定索引With(index=XXX)(我们一般使用With(index=XXX)在查询中指定索引)的表现随着数据的变化,查询语句指定的索引可能并不完美。它应该对应用程序透明。如果删除了指定的索引,会报查询错误,不利于排错。新创建的索引不能马上被应用使用,必须释放代码才能生效。variable/parameter/associatedfieldtype必须和字段类型一致(这个是我之前没怎么注意)避免类型转换额外消耗CPU,造成的大表扫描特别严重。看了上面两张图,我想不用解释了,大家应该都已经知道了。如果数据库字段类型为VARCHAR,则在应用程序中指定最大类型为AnsiString,并明确指定其长度如果数据库字段类型为CHAR,则在应用程序中指定最大类型为AnsiStringFixedLength,并明确指定其长度如果数据库字段类型为NVARCHAR,在应用中指定了***类型为String,并且明确指定了它的长度。参数化查询查询SQL可以通过以下方式参数化:sp_executesqlPreparedQueriesStoredprocedures用图说明,哈哈。限制JOIN的数量。单条SQL语句中表JOIN的个数不能超过5个,太多的JOIN会导致查询分析器执行计划出错。太多的JOIN在编译执行计划的时候消耗很大。限制IN子句中的条件数。IN子句中包含非常多的值(千)可能会消耗资源并返回错误8623或8632。要求IN子句中的条件个数限制在100个以内。尽量避免大事务operationsonlywhenthedatarequireupdate时才启动事务,减少资源锁持有时间,增加事务异常捕获预处理机制,禁止在数据库上使用分布式事务,用图说明我们不应该committranafter1000行数据都更新完了,你想想你更新这一千行数据是不是在独占资源,让其他事务处理不了。SQL语句中关闭返回受影响行数信息,设置SetNocountOn取消返回受影响行数信息,减少网络流量。除非必要,否则必须在SELECT语句中添加NOLOCK以指定允许脏读。不颁发共享锁是为了防止其他事务修改当前事务读取的数据,其他事务设置的排它锁不会阻止当前事务读取锁定的数据。允许脏读可能会导致更多并发操作,但代价是读取数据修改,稍后将被其他事务回滚。这可能会使您的事务出错,显示从未提交的用户数据,或导致用户看到记录两次(或根本看不到)使用UNIONALL而不是UNIONUNION将取消对SQL结果集的重新排序,增加消耗CPU、内存等查询大量数据使用分页或TOP合理限制返回记录条数避免IO和网络带宽瓶颈递归查询级别限制使用MAXRECURSION防止不合理的递归CTE进入***循环临时表和表变量使用局部适中的执行计划进行变量选择在存储过程或查询中,访问数据分布非常不均匀的表,往往会导致存储过程或查询使用次优甚至糟糕的执行计划,从而导致高CPU和大量IORead等问题,使用局部变量来防止错误的执行计划。使用局部变量的方式,SQL在编译的时候并不知道这个局部变量的值。这时,SQL会根据表中数据的大致分布情况,“猜测”出一个返回值。无论用户在调用存储过程或语句时代入的变量值是什么,生成的计划都是一样的。这样的计划一般比较温和,不一定是最好的计划,但一般也不是最坏的计划。如果不等运算符用于查询中的局部变量,查询分析器使用简单的30%计算来估计EstimatedRows=(TotalRows*30)/100如果相等运算符用于查询中的局部变量,则查询分析器uses:Accuracy*totaltablerecordstoestimateEstimatedRows=Density*TotalRows尽量避免使用OR运算符对于OR运算符,通常使用全表扫描,考虑分解成多个查询,使用UNION/UNIONALL要做到这一点,需要确认查询可以到索引,返回较少的结果集。增加事务异常处理机制。设置连接属性“setxact_aborton”以对输出列使用两段式命名格式。二段命名格式:表名。具有JOIN关系的字段名TSQL,该字段必须说明该字段属于哪个表,否则以后表结构变化后,可能会出现Ambiouscolumnname程序兼容性错误架构设计读写分离schema解耦数据生命周期读写分离一开始就设计了读写分离,即使读写同一个库,也有利于根据读的特点快速扩容和读点对于实时读和延时读,对应写库而读库读写分离要考虑在读不可用时自动切换到写端Schema解耦。禁止跨数据库JOIN。定期分库归档主库/归档库物理分离。日志类型的表应该分区或分区。对于大表,需要分区。分区操作将表和索引分成多个分区。通过分区切换可以快速更换新旧分区。加速数据清洗,大幅降低IO资源消耗频繁写入的表需要分区或子表自增长,LatchLatch闩锁由SQLServer内部应用和控制,用户无从干预保证数据结构在内存一致性,锁级别是页级锁