显然是防止SQL注入的最佳方法is to use prepared statements。但是,准备好的陈述是为其他东西设计的:
在数据库管理系统中,准备好的语句或参数化 statement是用于执行相同或类似数据库的功能 高效率的反复陈述 [...]
另一方面,如果查询仅在服务器端执行一次 由于额外的往返,准备好的陈述可能会更慢 到服务器。实施限制也可能导致性能 惩罚:某些版本的MySQL没有缓存准备的结果 查询和一些DBMS(如PostgreSQL)不执行其他操作 执行期间的查询优化。
我猜测准备好的语句主要用于在紧密循环中使用,以减少重复语句的编译时间。 SQL注入预防只是一个奖励。
假设我们没有使用PDO或“模拟”预处理语句,那么对于在页面上只使用一次的查询使用预准备语句是否有意义。
答案 0 :(得分:0)
只是一个个人的想法..
尽管每页执行一次的SQL语句可能会受到性能损失,但我认为这是有道理的。
每个应用程序通常都包含SQL语句的组合。有些只执行一次。有的多次。但是,人们通常不会忽略某些地方的SQL注入。通过应用程序对所有参数进行参数化可使代码更加一致。也许更优雅(例如,如果我考虑strings
中的撇号 - 不必通过将它们加倍来逃避它们等)。准备好的陈述负责所有这些。我从未测量过参数化查询的性能损失,但是如果遇到任何性能问题,我可能永远不会关注它们。如果我遇到性能问题,通常意味着其他问题(执行计划,正确索引,统计等)。
答案 1 :(得分:0)
答案当然取决于你正在使用的RDBMS。
对于网络应用程序,我会将安全问题评为高于性能问题,特别是如果性能差异可能几乎无法估量。
尽管如此,Oracle(以及其他RDBMS可能也是如此)区分了软解析和硬解析。当要求Oracle准备语句时,它首先计算语句的哈希值,并将其与已准备好的语句列表进行比较。如果在此列表中找到它,Oracle知道它已经解析了该语句,并且不需要再次解析它。这称为软解析。如果语句确实新(因此在此列表中找不到),则必须对语句进行硬解析。通常认为硬解析比软解析成本高得多。
因此,当您的应用程序每页只发出一次语句时,RDBMS仍会多次看到相同的语句,并且能够从第二次开始软解析语句。对于每个页面请求使用不同语句的替代方法,这甚至是一个巨大的好处,因为在替代方案中,每个语句都必须进行硬解析。
答案 2 :(得分:0)
以下内容适用于SQL Server
单个预处理语句可能比ad hoc查询执行得更糟。但是,整体性能应该更好。
准备好的声明表现比特别查询差
假设我们有一个表格,其中包含过去 10年和10种可能状态的记录。假设数据是均匀分布的,我们有这些查询:
... WHERE date >= '2017-01-01' AND status = 1
... WHERE date >= '2009-01-01' AND status = 1
... WHERE date >= ? AND status = ?
对于前两个查询(ad hoc),SQL Server可以为每个查询生成单独的执行计划,例如在第一个查询的日期列上使用索引,在第二个查询的状态列上使用索引。
对于第三个查询(已准备好),SQL Server将生成一个执行计划,该计划最适合大多数情况,但不是全部。例如,SQL Server可能会生成一个执行计划,该计划使用日期列上的索引,这对于最近的日期而不是过去的日期是有效的。
即席查询执行情况比准备好的声明差
即席查询的一个问题是它们最终会导致计划缓存膨胀"。发生这种情况时,计划经常从计划缓存中被踢出,并在再次执行相同的查询时重新编译。查询编译是一个昂贵的过程。
<强>观察强>
将我的Web应用程序从即席查询转换为预准备语句后,我注意到执行时间显着改善。计划缓存膨胀被消除,查询不会像使用即席查询那样经常重新编译,从而节省宝贵的CPU周期和内存。