读书笔记之SQL注入漏洞和SQL调优

系统 1545 0
原文: 读书笔记之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). 过滤敏感字符

  过滤敏感字符的思路非常简单,由于恶意攻击者一般需要在输入框中输入的文本一般含有  or and select delete  之类的字符串片段,所以在拼接  SQL  之前检查用户提交的文本中是否含有这些敏感字符串,如果含有则终止操作。

  2).使用参数化 SQL

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

 

2. SQL  调优 

  在使用  DBMS  时经常对系统的性能有非常高的要求:不能占用过多的系统内存和 CPU  资源、要尽可能快的完成的数据库操作、要有尽可能高的系统吞吐量。如果系统开发出来不能满足要求的所有性能指标,则必须对系统进行调整,这个工作被称为调优。

  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" 不能被有效的评估匹配的数量。 

  如果您有什么问题,欢迎在下面评论,我们一起讨论,谢谢~

  如果您觉得还不错,不妨点下右下方的推荐,有您的鼓励我会继续努力的~

 

读书笔记之SQL注入漏洞和SQL调优


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论