[SQL SERVER系列]读书笔记之SQL注入漏洞和SQL调优

  最近读了程序员的SQL金典这本书,以为里面的SQL注入漏洞和SQL调优总结得不错,下面简单讨论下SQL注入漏洞和SQL调优。程序员

1. SQL注入漏洞

  因为“'1'='1'”这个表达式永远返回 true,而 true 与任何布尔值的 or 运算的结果都是 true,那么不管正确密码是什么“Password='1' or '1'='1'”的计算值永远是 true,这样恶意攻击者就可使用任何账户登陆系统了。这样的漏洞就被称做“SQL 注入漏洞(SQL Injection)”。数据库

  对付 SQL 注入漏洞有两种方式:过滤敏感字符和使用参数化 SQL。 服务器

  1).过滤敏感字符网络

  过滤敏感字符的思路很是简单,因为恶意攻击者通常须要在输入框中输入的文本通常含有 orandselectdelete 之类的字符串片断,因此在拼接 SQL 以前检查用户提交的文本中是否含有这些敏感字符串,若是含有则终止操做。函数

  2).使用参数化SQL性能

  为运行时才能肯定的用户名和密码设置了占位符,而后在运行时再设定占位符的值,在执行时 JavaC#会直接将参数化 SQL 以及对应的参数值传递给 DBMS,在 DBMS 中会将参数值当成一个普通的值来处理而不是将它们拼接到参数化 SQL ,所以从根本上避免了 SQL 注入漏洞攻击。优化

 

2. SQL 调优 

  在使用 DBMS 时常常对系统的性能有很是高的要求:不能占用过多的系统内存和CPU 资源、要尽量快的完成的数据库操做、要有尽量高的系统吞吐量。若是系统开发出来不能知足要求的全部性能指标,则必须对系统进行调整,这个工做被称为调优。spa

  SQL 调优的基本原则   排序

  “二八原理”是一个广泛的真理,特别是在计算机的世界中表现的更加明显,那就是 20%的代码的资源消耗占用了 80%的总资源消耗。SQL 语句也是一种代码,所以它也符合这个原理。在进行 SQL 调优的时候应该把主要精力放到这 20%的最消耗系统资源的 SQL 语句中,不要想把全部的 SQL 语句都调整到最优状态。   索引

  索引是数据库调优的最根本的优化方法。

  经常使用的SQL调优方法:

  1) 建立必要的索引

  2) 使用预编译查询 

  程序中一般是根据用户的输入来动态执行 SQL 语句,这时应该尽可能使用参数化SQL,这样不只能够避免 SQL 注入漏洞攻击,最重要数据库会对这些参数化 SQL 执行预编译。

  3) 调整 WHERE 子句中的链接顺序 

  DBMS 通常采用自下而上的顺序解析 WHERE 子句,根据这个原理,表链接最好写在其余 WHERE 条件以前,那些能够过滤掉最大数量记录。 

  好比下面的 SQL 语句性能较差: SELECT *   FROM T_Person WHERE   FSalary > 50000  AND     FPosition= MANAGER’  AND     25 < (SELECT COUNT(*) FROM T_Manager WHERE FManagerId=2);  

  咱们将子查询的条件放到最前面,下面的 SQL 语句性能比较好: SELECT *   FROM T_Person WHERE   25 < (SELECT COUNT(*) FROM T_Manager WHERE FManagerId=2) AND FSalary > 50000  AND     FPosition= MANAGER’ 

  4) SELECT 语句中避免使用'*' 

  SELECT  *比较简单,可是除非确实须要检索全部的列,不然将会检索出不须要的列,这回增长网络的负载和服务器的资源消耗;即便确实须要检索全部列,也不要使用SELECT *,由于这是一个很是低效的方法,DBMS 在解析的过程当中,会将*依次转换成全部的列名,这意味着将耗费更多的时间。

  5) 尽可能将多条 SQL 语句压缩到一句 SQL 

  每次执行 SQL 的时候都要创建网络链接、进行权限校验、进行 SQL 语句的查询优化、发送执行结果,这个过程是很是耗时的,所以应该尽可能避免过多的执行 SQL 语句,可以压缩到一句 SQL 执行的语句就不要用多条来执行。

  6) 用 Where 子句替换 HAVING 子句  

  避免使用 HAVING 子句,由于 HAVING  只会在检索出全部记录以后才对结果集进行过滤。若是能经过 WHERE 子句限制记录的数目,那就能减小这方面的开销。HAVING  中的条件通常用于聚合函数的过滤,除此而外,应该将条件写在 WHERE 子句中。 

  7) 使用表的别名 

  当在 SQL 语句中链接多个表时,请使用表的别名并把别名前缀于每一个列名上。这样就能够减小解析的时间并减小那些由列名歧义引发的语法错误。 

  8) 用 EXISTS 替代 IN  

  在查询中,为了知足一个条件,每每须要对另外一个表进行联接,在这种状况下,使用 EXISTS 而不是 IN 一般将提升查询的效率,由于 IN 子句将执行一个子查询内部的排序和合并。

  9) 用表链接替换 EXISTS   

  一般来讲,表链接的方式比 EXISTS 更有效率,所以若是可能的话尽可能使用表链接替换 EXISTS

  10) 避免在索引列上使用计算 

  在 WHERE 子句中,若是索引列是计算或者函数的一部分,DBMS 的优化器将不会使用索引而使用全表扫描。

  11) 用 UNION ALL  替换 UNION  

  当 SQL 语句须要 UNION 两个查询结果集合时,即便检索结果中不会有重复的记录,若是使用 UNION 这两个结果集一样会尝试进行合并,而后在输出最终结果前进行排序。 所以,若是检索结果中不会有重复的记录的话,应该用 UNION ALL 替代 UNION,这样效率就会所以获得提升。

  12) 避免隐式类型转换形成的全表扫描 

  13) 防止检索范围过宽   

  若是 DBMS 优化器认为检索范围过宽,那么它将放弃索引查找而使用全表扫描。下面是几种可能形成检索范围过宽的状况: 使用 IS NOT NULL 或者不等于判断,可能形成优化器假设匹配的记录数太多。 使用 LIKE 运算符的时候,"a%"将会使用索引,而"a%c""%c"则会使用全表扫描,所以"a%c""%c"不能被有效的评估匹配的数量。 

  

  若是您有什么问题,欢迎在下面评论,咱们一块儿讨论,谢谢~

  若是您以为还不错,不妨点下右下方的推荐,有您的鼓励我会继续努力的~

相关文章
相关标签/搜索