-5

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

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

请告诉我如何提高页面的性能?

4

3 回答 3

3

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

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

set timing on
set autotrace traceonly statistics

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

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

如果需要更多时间,则意味着行非常大(许多大列),或者您的高水位线异常大。

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

于 2013-05-06T12:12:31.243 回答
2

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

所以这里有一些观察。

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

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

...并在评论中:

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

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

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

即便如此,在数据库中获取两万行数据需要 50 秒的时间,除非这些行真的很长。或者没有足够的内存来对哈希连接进行排序,所以它正在分页到磁盘。


“ 50 秒是合理的时间吗?”

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

正如我已经说过的,您案件的具体细节很重要。但是你没有提供任何细节,所以你可以拥有的只是一般性。总的来说,我会说几乎一分钟时间太长而无法加入并选择一个?二?二十?两张微不足道的小桌子上的任何行。

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

于 2013-05-06T13:01:53.080 回答
1

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 some_table 查询比 INSERT INTO some_table (SELECT ...) 运行得更快,在另一些情况下 INSERT INTO 更快。请注意,RequestLive 属性可能会对这些查询的性能产生影响。

于 2013-05-06T11:57:45.700 回答