\\ ubsp;
有很多关于SQL优化的在线教程,但是它们很混乱。最近,我有时间整理并写出来与大家分享。如果有错误和不足之处,请纠正它们。
我在本文上花费了大量时间来查找信息,进行修改和排版。
\\ ubsp;
1.为了优化查询,尽可能避免全表扫描,首先考虑在where和order by所涉及的列上建立索引。
2.尝试避免对where子句中的字段进行空值判断,否则将导致引擎放弃使用索引并执行全表扫描,例如:
从t中选择编号,其中num为null
最好不要为数据库保留NULL,请使用\。 NOT NULL尽可能地填充数据库。
备注,描述,注释等可以设置为\\ n。 NULL,否则,最好不要使用NULL。
不要以为\\ n NULL \\ n不需要空格,例如:char(100)\\ n,当字段建立时,空格是固定的,无论是否插入该值(还包括NULL),它都被占用。 100个字符的空间(如果它是可变长度的字段,如varchar)。空\\ n不会占用空间。
您可以将num的默认值设置为0,确保表中的num列没有空值,然后按以下方式查询:
从t那里选择id,其中num = 0
3.尽量避免使用! =或\ lt; \ gt;运算子在where子句中,否则引擎将放弃使用索引并执行全表扫描。
4.尽量避免在where子句中使用或来加入条件。如果一个字段有一个索引而一个字段没有索引,它将使引擎放弃使用索引并执行全表扫描,例如:
从t中选择id,其中num = 10或Name =" admin"
您可以这样查询:
从t中选择id,其中num = 10
全部合并
从t中选择id,其中Name =" admin"
5.in和not in也应谨慎使用,否则将导致全表扫描,例如:
从t中选择ID,其中(1,2,3)中的num
对于连续值,请使用而不是in:
从t中选择ID,其中num在1到3之间
很多时候,使用\\ n是一个不错的选择。存在而不是在\中:
从num中选择num(从b中选择num)
替换为以下语句:
从存在的位置中选择num(从b中选择1,其中num = a.num)
6.以下查询也将导致全表扫描:
从t中选择ID,其中的名称类似于"%abc%\\ rs00";
为了提高效率,可以考虑全文搜索。
7.如果在where子句中使用参数,还将导致全表扫描。由于SQL仅在运行时解析局部变量,因此优化器无法将访问计划的选择推迟到运行时;它必须在编译时选择。但是,如果在编译时建立了访问计划,则变量的值仍然未知,因此不能用作索引选择的输入。以下语句将执行全表扫描:
从t中选择id,其中num = @ num
可以强制查询使用索引代替:
使用(index(index name))从t中选择id,其中num = @ num
。您应该尝试避免对where子句中的字段执行表达式操作,这将导致引擎放弃使用索引并执行全表扫描。如:
从t中选择id,其中num/2 = 100
应该更改为:
从t中选择id,其中num = 100 * 2
9.您应该尝试避免对where子句中的字段进行函数操作,这将导致引擎放弃使用索引并执行全表扫描。如:
从t中选择ID,其中子字符串(名称,1,3)= \\ rs00; abc \\ rs00;-\ ndash;名称以abc的ID开头
从t中选择id,其中datediff(day,createdate,2005-11-30 \\ prime;)= 0-\\ ndash; \ lsquo; 2005-11-30--id生成
应该更改为:
从t中选择ID,其中名称如" abc%"
从创建的地方选择ID。 =" 2005-11-30"并创建\ lt; " 2005-12-1"
10.不要在函数的左侧执行函数,算术运算或其他表达式运算。 = \ rdquo;在where子句中,否则系统可能无法正确使用索引。
11.使用索引字段作为条件时,如果索引是复合索引,则必须使用索引中的第一个字段作为条件,以确保系统使用索引,否则index不会使用,字段顺序应尽可能匹配索引顺序。
12.如果需要生成一个空的表结构,请不要编写一些毫无意义的查询:
从t那里选择col1,col2进入#t,其中1 = 0
这种类型的代码不会返回任何结果集,但是会消耗系统资源,应将其更改为:
创建表#t(\ hellip;)
13.Update语句,如果仅更改一个或两个字段,则不要更新所有字段,否则频繁调用将导致大量的性能消耗并带来大量日志。
14.对于具有大量数据的表JOIN(此处认为有几百个大表),必须首先进行页面处理,然后再进行JOIN,否则逻辑读取会很高,并且性能非常好较差的。
15.从表格中选择计数(*);没有任何条件的此计数将导致全表扫描,并且对业务没有任何意义,因此必须杜绝。
16.索引越少越好,尽管索引可以提高相应选择的效率,但也会降低插入和更新的效率,因为在插入或更新时可能会重建索引,因此根据具体情况,如何构建索引需要仔细考虑。表中的索引数不应超过六个。如果索引太多,则应考虑是否需要建立在不经常使用的列上的索引。
17.您应该避免尽可能地更新聚簇索引数据列,因为聚簇索引数据列的顺序是表记录的物理存储顺序。一旦列的值更改,整个表记录的顺序将被调整,将消耗大量资源。如果应用程序系统需要经常更新聚簇索引数据列,则需要考虑是否应将索引构建为聚簇索引。
18.尽可能使用数字字段,如果仅包含数字信息的字段未设计为字符类型,则会降低查询和连接的性能,并会增加存储开销。这是因为引擎在处理查询和连接时会一一比较字符串中的每个字符。对于数字类型,只需要比较一次。
19.使用varchar/nvarchar代替char/nchar \尽可能多,因为首先可变长度字段的存储空间很小,可以节省存储空间,其次,在相对较小的字段中用于查询,内部搜索效率显然更高。
20.不要在任何地方使用select * from t,而要使用特定的字段列表,而不要使用\。 *,不返回任何未使用的字段。
21.尝试使用表变量而不是临时表。如果表变量包含大量数据,请注意索引非常有限(仅主键索引)。
22.避免频繁创建和删除临时表以减少系统表资源的消耗。临时表并非不可用。正确使用它们可以使某些例程更有效,例如,当您需要重复引用大型表或常用表中的数据集时。但是,对于一次性事件,最好使用导出表。
23.创建临时表时,如果一次插入大量数据,则可以使用select into代替create table以避免大量日志提高速度;如果数据量不大,为了减轻系统表的资源,您应该首先创建表,然后插入。
24.如果使用了临时表,则必须在存储过程的末尾显式删除所有临时表,首先截断表,然后删除表,以避免长时间锁定系统表。
25.尽量避免使用游标,因为游标的效率很差,如果游标操作的数据超过10,000行,则应考虑重写。
26.在使用基于游标的方法或临时表方法之前,应首先寻找基于集合的解决方案来解决该问题。基于集合的方法通常更有效。
27.与临时表一样,游标并非不可用。对于小型数据集,使用FAST_FORWARD游标通常比其他逐行处理方法更好,尤其是在必须引用多个表来获取所需数据的情况下。结果集中包含”总计”的例程通常比使用游标执行得更快。如果开发时间允许,则可以尝试使用基于游标的方法和基于集合的方法来查看哪种方法更好。
28.在所有存储过程和触发器的开始处将SET NOCOUNT设置为ON,并在结束时将SET NOCOUNT OFF设置为。执行存储过程和触发器的每个语句后,无需向客户端发送DONE_IN_PROC消息。
29.尝试避免大型事务操作并提高系统并发性。
30.尽量避免将大量数据返回给客户端,如果数据量太大,则应考虑相应的需求是否合理。
实际案例分析:拆分大删除\或INSERT \语句,请分批提交SQL语句
如果需要执行较大的语句,请执行以下操作。在在线网站上DELETE \或\插入\查询时,您需要非常小心,以免您进行操作以阻止整个网站响应。因为这两个操作将锁定表,所以一旦表被锁定,其他任何操作都无法输入。
Apache \\\将有许多子进程或线程。因此,它非常有效,并且我们的服务器不希望有太多的子进程,线程和数据库链接,这是非常大的事情,会占用服务器资源,尤其是内存。
如果锁定表一段时间(例如30秒),则对于流量较高的站点,访问进程/线程,数据库链接以及在这30秒内累积的打开文件不仅会使您的Web服务崩溃,还会使整个服务器立即挂断。
因此,如果您有很多事情,则必须使用将其拆分。 LIMIT \\ ubsp; oracle(rownum),sqlserver(top)条件是一个很好的方法。这是一个mysql示例:
而(1){
//每次只有1000
Mysql_query(从目录中删除log_date \\ = 2012-11-01 \\限制为1000 \\)
如果(mysql_affected_rows()== 0){
//删除完成,退出!
打破;
}
//在一段时间内,每次释放表以允许其他进程/线程访问。
睡着了(50000)
}
好的,我将在这里写完。我知道仍然有很多未写的,请补充。稍后,我将向大家介绍一些SQL优化工具。让我们一起学习,共同进步!