我有二十年的SQL经验,但不是专门针对Oracle的。 “Oracle专家”向我保证,在没有参数的情况下构建SQL查询(如下所示):
SELECT t.ID, t.Name, t.Address ... FROM Table1 t WHERE t.ID = 'someID' AND t.Name = 'someName'...
至少和使用参数一样快(像这样)
SELECT t.ID, t.Name, t.Address ... FROM Table1 t WHERE t.ID = ? AND t.Name = ?
代码循环执行。
在我遇到的大多数其他数据库中,使用参数可以提高速度。它允许数据库缓存与SQL语句匹配的已编译计划。由于SQL不会因每次调用而更改(尽管参数可以),因此可以提高性能。数据库只是绑定参数并继续。
“Oracle专家”指出这不是必需的。但显然,Oracle需要“解析”参数,将剩余的字符串与缓存的执行计划相匹配,然后重新绑定参数,就像它们首先作为参数传递一样。
我在这里有正确的心理图片吗?有没有关于Oracle的“神奇”信息,我们如何处理参数传递/ SQL构建策略真的没有什么区别?
是否有关于Java / JDBC / Oracle瘦驱动程序的想法,我不知道我应该知道这里?
我希望加强理解或扩展我的知识。
(请放置安全问题,我理解构建SQL字符串允许SQL注入攻击,我正在寻找更多的直接弹药来对抗专家意见 - 如果存在的话)。
其他详情:Oracle 11gR2, Java 1.6
答案 0 :(得分:4)
直言不讳 - 你做对了,你的Oracle专家似乎根本就不是专家(除非他想把你的应用程序投入生产后出售昂贵的咨询时间)。
如果构建没有参数的SQL语句(在Oracle中称为绑定变量),则每次执行时都强制数据库对语句进行硬解析。
有关更好的解释,请参阅AskTom on soft/hard parsing and bind variables。
答案 1 :(得分:3)
使用参数几乎总是优选的。如果使用文字(版本1),数千个略有不同的SQL语句将命中数据库,从而导致硬分析并填满Oracle的语句缓存。
以下是规则的一个例外:如果您要查询值分布非常不均匀的列,则带有文字的版本可能允许查询优化器找到更好的计划。
例如,假设绝大多数的slashdot读者是男性(*),
select * from slashdot_readers where gender='MALE';
可能会导致查询优化器忽略gender
上的索引,而是执行全表扫描,而
select * from slashdot_readers where gender='FEMALE';
可能会导致它使用索引。使用变量,查询优化器将不知道要使用哪个版本,因此它可能始终执行全表扫描。
(*)仅仅是为了这个例子
答案 2 :(得分:1)
我没有做任何性能测量,但我认为你的图片是正确的。在任何情况下,即使它们同样快,我总是更喜欢使用参数/绑定变量来防止SQL注入。这可能不是你的示例中你在where子句中有固定字符串的问题,但在实际应用中,这些字符串通常来自外部的某个地方。 (我想你刚写完这个答案时编辑了你的问题:-))
答案 3 :(得分:1)
做一些测量。获取数据。
从我所知道的关于Oracle的一切 - 你应该是对的。显然要确保它是否在一个循环中,你重新执行相同的PreparedStatement
而不是每次都重新准备它。仅此一项就可以降低查询成本。
有一点需要注意 - 您的实际应用程序甚至可以从绑定变量中获得 more 而不是简单的测试用例,因为在实际应用程序中,Oracle将在其缓存中包含各种其他SQL语句(我忘记了目前Oracle中不同内存区域和缓存的术语),并且随着填充,新SQL的发送成本会相当高。