我有20年的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有没有什么“神奇”的地方,它真的不会改变我们如何处理参数传递/SQL构建策略?
关于Java / JDBC / Oracle thin driver,有没有我不知道的,但在这里我应该知道的?
我希望要么加强我的理解,要么扩展我的知识。
(请把安全问题放在一边,我知道构建SQL字符串允许SQL注入攻击,我正在寻找更直接的证据来反对专家的意见-如果它存在的话)。
其他细节:Oracle 11gR2, Java 1.6
发布于 2012-10-15 21:44:56
坦率地说,你做得很对,而你的Oracle专家似乎根本就不是专家(除非他想卖出昂贵的咨询时间,以便在你将应用程序投入生产后加快它的速度)。
如果构建不带参数的SQL语句(在Oracle中称为绑定变量),则会强制数据库在每次执行语句时对其进行硬解析。
更好的解释请参见AskTom on soft/hard parsing and bind variables。
发布于 2012-10-15 21:49:53
使用参数几乎总是可取的。如果使用文字(版本1),数千条稍有不同的SQL语句将命中数据库,导致硬解析并填满Oracle的语句缓存。
以下是该规则的一个例外:如果要查询的列的值分布非常不均匀,则包含文字的版本可能允许查询优化器找到更好的计划。
例如,假设绝大多数slashdot阅读器是男性(*),
select * from slashdot_readers where gender='MALE';可能会导致查询优化器忽略gender上的索引,而改为执行全表扫描
select * from slashdot_readers where gender='FEMALE';可能会导致它使用索引。使用变量时,查询优化器将不知道要使用哪个版本,因此它可能始终执行全表扫描。
(*)就本例而言
发布于 2012-10-15 21:41:56
我没有做任何性能测量,但我认为您的照片是正确的。在任何情况下,即使它们同样快,我总是更喜欢使用参数/绑定变量的变体,以防止SQL注入。这在您的示例中可能不是问题,因为在where子句中有固定的字符串,但在实际应用程序中,这些字符串通常来自外部。(我想你在我写这个答案的时候编辑了你的问题:-)
https://stackoverflow.com/questions/12896752
复制相似问题