2011-06-27 122 views
3

该项目是ASP/VB.net中的一个Web应用程序。问题在于,有些页面非常缓慢。在尝试追查瓶颈后,发现它是用查询结果填充数据表时的加载方法。为什么datatable的加载方法有时非常慢?

我们正在使用Oracle数据库,并在存储过程中执行查询。作为一个例子,我们在一个过程中有一个相对简单的select语句,该过程返回2列6行,这被确定需要大约0.015秒来执行。但是,平均需要7秒才能将OracleDataReader加载到数据表中 - 对于这样一个小记录集来说,这是一个荒谬的时间。在查询之后,我发现一个简单的解码语句似乎导致了这个问题。译码语句用于类似于如下:

WHERE DECODE(iBln,1,列1,列2)BETWEEN iDate1和iDate2

的iBln变量被简单地传递在一个号码,作为一个布尔变量用于确定哪个列应该在两个日期之间。如果我注释这个解码语句,并简单地将其设置为“column1 BETWEEN iDate1和iDate2”,那么加载方法根本不需要任何时间,这意味着它确实是导致问题的解码语句。

所以我只是希望听到任何人可以有一个想法是什么导致这个或如何解决它。这是一个简单的解码,它如何影响负载方法呢?

回答

4

我会验证列1和列2的索引存在。如果是这样,可能的问题是DECODE正在阻止使用索引。尝试为改写:

WHERE ((iBin = 1 AND column1 BETWEEN iDate1 AND iDate2) 
     OR 
     ((iBin IS NULL OR iBin <> 1) AND column2 BETWEEN iDate1 AND iDate2) 
    ) 
+0

这很棒!我向Justin Cave提出了这个问题,因为我仍然很好奇 - 你知道为什么DECODE会阻止在存储过程中使用查询时使用索引,但是当我运行查询时索引工作得很好本身在查询工具中? – Nick

+0

@ ibar98:当您交互式地执行查询时,是否为'iBin'硬编码了一个值?如果是这样,那可能已经允许解析器将DECODE表达式解析为单个列名称,因此使用索引访问路径。 –

+0

啊是的,我做了硬编码的价值。我只是没有意识到解析器会走这么远来优化查询。感谢所有的帮助! – Nick

3

如果您的存储过程正在返回REF CURSOR,则无论您正在执行的查询如何,在存储过程中打开游标都将非常快速。打开游标并不要求Oracle执行任何实际运行查询的工作,只需要Oracle确定应该或多或少是瞬时的查询计划。

需要多长时间从REF CURSOR中获取数据,例如SQL * Plus?如果需要接近7秒的时间(因为我怀疑它会这样),那么可以将OracleDataReader类作为问题的根源。在这种情况下,问题几乎可以肯定是查询计划效率低下。

根据您的描述,我的猜测是column1被编入索引。 column2也可能被编入索引,目前还不清楚。但是column1column2的常规索引不能用于评估涉及调用DECODE函数的谓词。如果在索引列上没有其他谓词,那么可能会强制Oracle对基础表执行表扫描(发布完整查询,表定义和查询计划将会很有帮助)。

+0

这绝对是有道理的,我跑了一些测试,以证明我们的测试程序确实指责负载法的时间量花了查询运行。然而,当我将select语句从存储过程(带有解码函数的这个存储过程)中提取出来并运行到我们的查询工具(该公司使用Benthic Golden6)时,它使我快速而完美地执行。有没有理由认为DECODE会在存储过程中调用时否定使用索引,而不是直接在查询中调用? – Nick

+0

@ ibar98 - 您是否在描述相同的场景,您是在回复Dave的问题时对'iBin'的值进行了硬编码(从而允许Oracle在解析时评估DECODE)?还是这是一个不同的测试? –

+0

是的,这是相同的情况,现在它变得更有意义。你和戴夫非常有帮助,我真的很感谢你给我的所有帮助。 – Nick