有什么方法可以减少Select查询所花费的时间?

时间:2013-05-06 11:53:52

标签: sql performance oracle jsp query-optimization

我正在JSP中为我的oracle数据库创建一个API。

我有两个表,每个表包含20k条记录。我需要执行自然连接,结果将以JSON格式显示在JSP页面中。我的问题是加载JSON页面花了将近3分钟。

请告诉我如何改善页面的效果?

3 个答案:

答案 0 :(得分:2)

要优化流程(任何流程!),您需要了解花费时间的位置。如果你在数据库中花费10秒,在java中花费170秒,你不想从显然优化查询开始。

您应该做的第一件事是直接在数据库中运行查询,并使用最小的图形显示,例如在SQL * Plus中使用:

set timing on
set autotrace traceonly statistics

这将让您大致了解从数据库中获取的时间。最有可能连接两个20k行的小表,这不应超过1秒。

在数据库服务器上运行查询以消除任何网络延迟。

如果需要更多时间,则表示行非常大(许多大列)或者您的异常大high water mark

我认为Oracle正在为查询选择正确的计划(由于您没有使用WHERE条件,因此应该是FULL SCAN + HASH JOIN。)

答案 1 :(得分:1)

首先,你应该知道,有些顾问通过调整其他人的简单代码来做很好的生活。如果性能优化仅仅是一些规则的问题,他们就无法做到这一点。你案件的具体细节真的很重要。

所以这里有几点意见。

我们有两个感兴趣的陈述。在问题机构中:

  

“我的问题是加载JSON页面花了将近3分钟。”

......在评论中:

  

“在oracle中平均需要超过50秒”

这表明大多数时间在数据库中使用。因此,调优的第一个重点应该是前端代码或网络。 20,000行的结果集 - 包括来自两个表的记录 - 可能是很多数据包。也许您的网络/系统管理员可以提供建议。

要检查的一件事是,您要从数据库中收集信息,而不是逐行(或者更糟糕的是,逐个属性)。

即便如此,50秒是很多时间在数据库中获得两万行,除非行非常长。或者没有足够的内存来对散列连接进行排序,因此它会分页到磁盘。


  

“50秒是一个可重复的时间吗?”

定义合理的。如果我是一个用户,并且我在手机上有一个客户,并且在此查询返回之前我无法回复它们,那么当然这是完全不可接受的。但是,如果这是一个异步Web服务,它在完成时将消息放入队列中,并且我可以在下一个小时的任何时间处理它,那么50秒就可以了。

正如我已经说过,您案件的具体细节很重要。但是你还没有提供任何细节,所以你可以拥有一般性。总的来说,我会说差不多一分钟 太长了,无法加入并选择一个?二?二十?来自两个平凡小桌子的任何行。

但是让我重复一遍:五十秒不到您说填充页面所花费的总时间的一半。如果你传回少量几行而不是两万行,那么其他130秒就会变得更加明显。

答案 2 :(得分:0)

来自WHERE子句

的条件的可用索引

建议确保WHERE子句中条件的最佳索引可用。 有关如何检查搜索条件和创建适当索引的更多详细信息,请参阅“加速搜索和过滤器”主题。 例如,如果您希望获得更好的查询性能:

SELECT * FROM customer WHERE City='Kapaa Kauai' AND State='HI' 

加快速度的最佳方法是创建以下区分大小写的索引:

ABSTable1.AddIndex('idxCityState', 'City;State', []);  

如果您需要为查询获得更好的性能:

SELECT * FROM customer WHERE Upper(City)='KAPAA KAUAI'  

加快速度的最佳方法是创建以下不区分大小写的索引:

ABSTable1.AddIndex('idxCity_nocase', 'City', [ixCaseInsensitive]);  

JOIN条件的可用索引

要改进JOIN查询,请检查JOIN条件中的每个字段是否都有索引。 例如,如果您想提高查询的性能:

SELECT Event_Name,Venue FROM Events e JOIN Venues v ON (e.VenueNo = v.VenueNo)  

您可以创建以下索引:

VenuesTable.AddIndex('idxVenueNo', 'VenueNo', [ixPrimary]);  
EventsTable.AddIndex('idxVenueNo', 'VenueNo', []);  

使用OR条件将查询重写为UNION

Absolute DB无法使用索引来提高OR条件的查询性能。你可以加快你的速度 查询

SELECT * FROM table WHERE (Field1 = 'Value1') OR (Field2 = 'Value2')  

通过在上述条件中的每个字段上创建索引并改为使用UNION运算符 使用OR:

SELECT ... WHERE Field1 = 'Value1'  
UNION  
SELECT ... WHERE Field2 = 'Value2'  

ORDER BY子句的可用索引

如果要使用ORDER BY子句从单个表中加速“实时”SELECT,可以为ORDER BY字段创建复合索引。 例如,如果您想提高查询的速度:

SELECT * FROM Employee ORDER BY LastName, FirstName  

您可以通过创建以下复合索引来实现:

ABSTable1.AddIndex('idxLastNameFirstName', 'LastName;FirstName', []);  

GROUP BY子句的可用索引

要从具有GROUP BY子句的单个表中获得SELECT的更好性能,可以为GROUP BY字段创建复合索引。 例如,如果您想加快查询速度:

SELECT * FROM Employee GROUP BY FirstName  

您可以创建以下索引:

ABSTable1.AddIndex('idxFirstName', 'FirstName', []);  

从内存表中选择

如果要将所有数据从磁盘表移动到内存表,并且您将使用磁盘表的内存中副本执行查询(在查询执行之前将TABSQuery.InMemory属性设置为True),也可以增加查询性能)。

SELECT INTO vs INSERT SELECT

在某些情况下,SELECT ... INTO some_table查询比INSERT INTO some_table(SELECT ...)运行得更快,在另一种情况下INSERT INTO更快。请注意,RequestLive属性可能会影响这些查询的性能。