SQL注入漏洞和SQL优化

一、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 注入漏洞攻击。优化

二、SQL 优化

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

SQL 优化的基本原则code

“二八原理”是一个广泛的真理,特别是在计算机的世界中表现的更加明显,那就是 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”不能被有效的评估匹配的数量。

相关文章
相关标签/搜索