我正在JSP中为我的oracle数据库创建一个API。
我有两个表,每个表包含20k条记录。我需要执行自然连接,结果将以JSON格式显示在JSP页面中。我的问题是加载JSON页面花了将近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属性可能会影响这些查询的性能。