使用时容易忽略SQLServer的21个问题

使用时容易忽略SQLServer的21个问题,第1张

使用时容易忽略SQLServer的21个问题,第2张

如果您负责一个基于SQL Server的项目,或者如果您不熟悉SQL Server,您可能会面临一些数据库性能问题。本文将为您提供一些有用的指导(其中大部分也可用于其他DBMS)。

在这里,我不打算介绍使用SQL Server的小技巧,也不能提供一个包治百病的解决方案。我做的就是总结一些经验——如何形成一个好的设计。这些经验来自于我这几年经历的教训。一直以来,我看到许多相同的设计错误一次又一次地重复。

你懂工具吗?

不要小看这一点,这是我在这篇文章里讲的最关键的一点。您可能还会看到,许多SQL Server程序员并不掌握所有的T-SQL命令和SQL Server提供的有用工具。

“什么?我要浪费一个月的时间去学习永远用不到的SQL命令???"你可以这么说。是的,你不需要这样做。但是你应该花一个周末浏览所有的T-SQL命令。在这里,你的任务就是要知道,将来,当你设计一个查询时,你会记住:“对了,这里有一个命令,可以完全实现我需要的功能。”所以,去MSDN检查这个命令的确切语法。

不要使用光标。

我再说一遍:不要用光标。如果你想破坏整个系统的性能,它们是你最有效的首选。大多数初学者在使用游标时没有意识到它们对性能的影响。它们以不可思议的方式占用内存和锁表。此外,它们像蜗牛。最糟糕的是,它们会让您的DBA所能做的所有性能优化都化为乌有。你知道吗,每次FETCH执行都相当于一个SELECT命令?这意味着如果您的游标有10,000条记录,它将执行10,000次SELECT!如果用一套SELECT,UPDATE或者DELETE来完成相应的工作,效率会高很多。

初学者普遍认为使用游标是一种熟悉且舒适的编程方法,但遗憾的是,这会导致性能不佳。很明显,SQL的总体目的是你想达到什么,而不是如何达到。

我曾经用T-SQL重写了一个基于游标的存储过程。那个表只有100,000条记录。原来的存储过程需要40分钟来执行,而新的存储过程只需要10秒钟。在这里,我想你可以看到一个不称职的程序员在做什么!!!

我们可以写一个小程序来获取和处理数据,更新数据库,这样有时候更有效。记住:T-SQL对循环无能为力。

我再提醒你一次:用光标没用。除了DBA的工作,我从来没见过有什么可以用cursor有效完成的。

规范化您的表。

为什么不将数据库标准化?大概有两个借口:性能考虑和纯粹的懒惰。至于第二点,你迟早要付出代价的。至于性能,你不需要优化任何一点都不慢的东西。我经常看到一些程序员“反规范化”数据库。他们的理由是最初的设计太慢,但结果是他们经常让系统变慢。DBMS是为处理标准化的数据库而设计的,所以记住:根据标准化的要求来设计数据库。

不要使用SELECT *

这个不容易做到,我也很清楚,因为我自己也经常这么做。但是,如果在SELECT中指定所需的列,将会带来以下好处:

1减少内存消耗和网络带宽。

可以得到更安全的设计。

让查询优化器有机会从索引中读取所有必需的列。

明白你要用这些数据做什么。

为数据库创建一个健壮的索引是一个优点。但是要做到这一点简直就是一门艺术,每次给表添加索引,SELECT会快一些,但是INSERT和DELETE会慢很多,因为创建和维护索引需要做很多额外的工作。很明显,这里的问题关键在于:你想用这种形式做什么样的操作?这个问题不太好把握,尤其是在删除和更新的时候,因为这些语句往往在WHERE部分包含SELECT命令。
不要为“性别”列创建索引

首先,我们必须了解索引是如何加快访问表的速度的。您可以将索引理解为一种基于特定标准划分表的方法。如果为“性别”这样的列创建索引,只需将表分为两部分:男性和女性。您正在处理一个包含1,000,000条记录的表。这样的划分有什么意义?记住:维护索引需要时间。当你设计一个索引时,请遵循这个规则:根据一个栏目可能包含的不同内容的数量,按降序排列,例如:姓名+省份+性别。
使用事务

请使用事务,尤其是当查询很耗时的时候。如果系统有问题,这样做可以救你一命。一些有经验的程序员有经验——你会经常遇到一些意外情况,会导致存储过程崩溃。

小心死锁

按照一定的顺序访问您的手表。如果您先锁定表A,然后锁定表B,那么您应该在所有存储过程中按此顺序锁定它们。如果在存储过程中锁定表A之前(无意中)锁定了表B,可能会导致死锁。如果没有事先设计好锁序列,死锁就不容易被发现。
不要打开大型数据集。

在技术论坛上,一个经常被问到的问题是:怎样才能快速的给ComboBox添加10万条记录?这是不对的,你不能也不需要这么做。很简单。您的用户必须浏览100,000条记录才能找到他需要的记录。他会诅咒你。在这里,你需要的是更好的UI。您需要为您的用户显示不超过100或200条记录。

不要使用服务器端光标。

与服务器端游标相比,客户端游标可以减少服务器和网络的系统开销,也可以减少锁定时间。

带参数查询

有时候在技术论坛上看到这样一个问题:“SELECT * FROM a WHERE a.id='A'B,因为单引号查询有异常。我该怎么办?”,一般的回答是:用两个单引号代替单引号。这是不对的。这样治标不治本,因为其他角色你也会遇到这样的问题,更何况会导致严重的bug。除此之外,还会使SQL Server的缓冲系统无法发挥应有的作用。使用参数查询,锅底,这些问题都不存在。
程序编码使用数据量大的数据库

一般程序员在开发中使用的测试数据库数据量很小,但往往终端用户的数据量很大。我们通常的做法是错误的。原因很简单:现在硬盘不是很贵,但是为什么性能问题要等到不可修复的时候才被注意到呢?

不要使用INSERT来导入大量数据。

除非必要,请不要这样做。使用UTS或BCP,这样你就可以同时拥有灵活性和速度。

注意超时问题。

查询数据库时,一般数据库的默认值都比较小,比如15秒或者30秒。有些查询运行的时间比这个长,尤其是当数据库中的数据量不断增加时。
不要忽略同时修改同一条记录的问题。

有时,两个用户会同时修改同一个记录,这样后一个修订者修改前一个修订者的操作时会丢失一些更新。处理这种情况并不十分困难:创建一个时间戳字段,在写之前检查它,如果允许的话合并修改,如果有冲突就提示用户。

在明细表中插入记录时,不要在主表中执行SELECT MAX(ID)。

这是一个常见的错误。当两个用户同时插入数据时,会导致错误。您可以使用SCOPE_IDENTITY、IDENT_CURRENT和@@IDENTITY。如果可能的话,不要用@@IDENTITY,因为有触发器的时候会造成一些问题(详见这里的讨论)。

避免将列设置为可空。

如果可能,您应该避免将列设置为可空。系统会为每一行可空列多分配一个字节,这样在查询时会带来更多的系统开销。此外,将列设置为NULLable会使编码变得复杂,因为每次访问这些列时,都必须首先检查它们。

我并不是说NULLS是麻烦的根源,尽管有些人这样认为。我认为,如果在您的业务规则中允许“空 data”,那么,将列设置为NULLable有时会很好。但是,如果NULLable用在像下面这样的情况,那简直就是自找麻烦。

客户名称1
客户地址1
客户地址1
客户名称2
客户地址2
客户地址3
客户名称1
客户地址2
客户地址3

如果出现这种情况,您需要标准化您的表。

尽量不要使用文本数据类型

除非使用文本来处理大量数据,否则不要使用文本。因为不太好查询,所以比较慢,如果使用不当会浪费很多空房间。一般来说,VARCHAR可以更好地处理您的数据。

尽量不要使用临时表

除非万不得已,尽量不要使用临时表。可以使用常规子查询来代替临时表。使用临时表会带来系统开销。如果是用COM+编程,也会给你带来很大的麻烦,因为COM+使用数据库连接池但是临时表一直存在。SQL Server提供了一些替代方法,如表数据类型。

学会分析查询。

SQL Server查询分析器是您的好伙伴,通过它您可以了解查询和索引如何影响性能。

使用参照完整性

定义主键、性约束和外键,可以节省很多时间。

位律师回复
DABAN RP主题是一个优秀的主题,极致后台体验,无插件,集成会员系统
白度搜_经验知识百科全书 » 使用时容易忽略SQLServer的21个问题

0条评论

发表评论

提供最优质的资源集合

立即查看 了解详情