我一直在使用与spring和Hibernate 4.X.X集成的应用程序,其事务由Weblogic应用程序服务器中的JTA管理。 3年后,我的数据库中存在的100个表中只有大约4千万条记录。数据库是Oracle 11g。查询的响应时间约为5分钟,因为增加了此表的记录数。 我自定义了查询并将其放入Sql Developer并运行查询顾问计划以建议一些索引。完成此操作后,其响应时间缩短为2分钟。但即便如此,这个响应时间并不能满足客户的需求。为了进一步澄清我把查询,它如下:
select *
from (select (count(storehouse0_.ID) over()) as col_0_0_,
storehouse3_.storeHouse_ID as col_1_0_,
(DBPK_PUB_STOREHOUSE.get_Storehouse_Title(storehouse5_.id, 1)) as col_2_0_,
storehouse5_.Organization_Code as col_3_0_,
publicgood1_.Goods_Item_Id as col_4_0_,
storehouse0_.storeHouse_Inventory_Id as col_5_0_,
storehouse0_.Id as col_6_0_,
storehouse3_.samapel_Item_Id as col_7_0_,
samapelite10_.MAINNAME as col_8_0_,
publicgood1_.serial_Number as col_9_0_,
publicgood1_1_.production_Year as col_10_0_,
samapelpar2_.ID_SourceInfo as col_11_0_,
samapelpar2_.Pn as col_12_0_,
storehouse3_.expire_Date as col_13_0_,
publicgood1_1_.Status_Id as col_14_0_,
baseinform12_.Topic as col_15_0_,
publicgood1_.public_Num as col_16_0_,
cast(publicgood1_1_.goods_Status as number(10, 0)) as col_17_0_,
publicgood1_1_.goods_Status as col_18_0_,
publicgood1_1_.deleted as col_19_0_
from amd.Core_StoreHouse_Inventory_Item storehouse0_,
amd.Core_STOREHOUSE_INVENTORY storehouse3_,
amd.Core_STOREHOUSE storehouse5_,
amd.SMP_SAMAPEL_CODE samapelite10_
cross join amd.Core_Goods_Item_Public publicgood1_
inner join amd.Core_Goods_Item publicgood1_1_
on publicgood1_.Goods_Item_Id = publicgood1_1_.Id
left outer join amd.SMP_SOURCEINFO samapelpar2_
on publicgood1_1_.Samapel_Part_Number_Id =
samapelpar2_.ID_SourceInfo, amd.App_BaseInformation
baseinform12_
where not exists
(select ssec.samapelITem_id
from core_security_samapelitem ssec
inner join core_goods_item g
on ssec.samapelitem_id = g.samapel_item_id
where not exists (SELECT aa.groupid
FROM app_actiongroup aa
where aa.groupid in
(select au.groupid
from app_usergroup au
where au.userid = 1)
and aa.actionid = 9054)
and ssec.isenable = 1
and storehouse0_.goods_Item_ID = g.id)
and not exists
(select *
from CORE_POWER_SECURITY cps
where not exists (SELECT aa.groupid
FROM app_actiongroup aa
where aa.groupid in
(select au.groupid
from app_usergroup au
where au.userid = 1)
and aa.actionid = 9055)
and cps.inventory_id =
storehouse0_.storeHouse_Inventory_Id
and cps.goodsitemtype = 6)
and storehouse0_.storeHouse_Inventory_Id = storehouse3_.Id
and storehouse3_.storeHouse_ID = storehouse5_.Id
and storehouse3_.samapel_Item_Id = samapelite10_.MAINCODE
and publicgood1_1_.Status_Id = baseinform12_.ID
and 1 <> 2
and storehouse0_.goods_Item_ID = publicgood1_.Goods_Item_Id
and publicgood1_1_.edited = 0
and publicgood1_1_.deleted = 0
and (exists (select storehouse13_.Id
from amd.Core_STOREHOUSE storehouse13_
cross join amd.core_power power16_
cross join amd.core_power power17_
where storehouse5_.powerID = power16_.Id
and storehouse13_.powerID = power17_.Id
and (storehouse13_.Id in (741684217))
and storehouse13_.storeHouseType = 2
and (power16_.hierarchiCode like
power17_.hierarchiCode || '%')) or
(storehouse3_.storeHouse_ID in (741684217)) and
storehouse5_.storeHouseType = 1)
and (storehouse5_.storeHouse_Status not in (2, 3))
order by storehouse3_.samapel_Item_Id)
where rownum <= 10
[注意:此查询由Hibernate生成] 很明显,4000万的订单占用了这么多时间。 我找到了这个查询的主要问题。我省略了“order by”并运行查询,其响应时间减少到大约5秒。我很好,为什么“order by”会影响响应时间。 (有些人可能认为如果这个表被分区或使用oracle的另一个工具,它可能会得到更好的响应时间。好吧可能是对的,但我强调的是“按顺序”表现。如果有办法可以做到“按“责任,为什么不这样做”。无论如何我都无法省略“order by”,因为客户需要订购并且必须进行分页。我找到了一个例子解释的解决方案。这个解决方案我只订购了一些需要的记录。怎么样,我稍后会解释。很明显,当oracle想要分类4000万条记录时,它自然需要花费很多时间。我将“order by”替换为“where子句”。通过这种替换,响应时间从2分钟减少到大约5秒,这对我来说非常令人兴奋。 我通过一个例子来解释我的解决方案,任何读过这篇文章的人都告诉我这个解决方案是好还是还有另一个我不知道的解决方案。 另一方面,我有一个解决方案,稍后会解释,如果它没有问题。我是否使用它。 我解释我的解决方案: 我们假设有两个表格如下:
Post table
Id Others fields
1
2
3
4
5
… …
Post_comment table
Id post_id
1 5
2 5
3 5
4 5
6 5
7 2
8 2
9 2
10 3
11 1
12 1
13 1
14 1
15 1
16 1
17 1
18 1
19 1
20 1
21 1
22 1
23 1
24 1
25 1
26 4
27 4
有一个表单显示POST表和POST_COMMENT表之间的连接结果 我用“order by”解释了该表的所有记录,并且“order by”只解释了所需的特定记录。两个查询的结果完全相同,但第二个方法的响应时间比那个更好 您假设页面大小为10,而您位于第3页 第一个查询带有“order by”该表的所有记录:
select *
from (Select res.*, rownum as rownum_
from (Select * from POST_COMMENT Order by post_id asc) res
Where rownum <= 30)
where rownum_ > 20
第二个解决方案:
在执行查询之前,我查询如下:
select *
from (select post_id, count(id) from POST_COMMENT group by post_id)
order by post_id asc
所以结果如下:
Post_id Count(id) Sum(count(id))
1 15 15
2 3 18
3 1 19
4 2 21
5 5 26
需要说第三列是&#34; Sum(count(id))&#34;在该查询之后计算。此列的任何条目都是记录前的总和 所以有一个公式,必须选择post_id的细节。公式如下:
pageSize = 10, pageNumber = 3
from : (pageNumber – 1) * pageCount 2 * 10 = 20
to : (pageNumber – 1) * pageCount + pageCount 20 + 10 = 30
所以我需要在Sum(count(id))的(20,30)之间的帖子。根据这个,我只需要两个值为4,5的post_id。根据这个第二种方法的主要查询是:
select *
from (select rownum as rownum_, res.*
from (select *
from (select * from POST_COMMENT where post_id in (4, 5))
order by post_id asc) res
where rownum <= 30)
where rownum_ > 20
如果你看两个查询,你会看到最大的区别。第二个查询只选择post_id为4和5的POST_COMENT记录。之后,命令记录的不是该表的所有记录。
答案 0 :(得分:0)
After posting this post, I have searched. finally I am redirected to HERE . I can reach to the response time that is very excited for me. It is reduced from 3 minutes to less than 3 seconds. It is necessary to know, I only use one tip from all of the query optimization guidelines that are in that site that is Duplicate constant condition for different tables whenever possible
.
Note: Before doing this tip, there are some indexs on fields that are in where-clause and order-by.