在oracle 11g中模拟流水线订单

问题描述 投票:0回答:1

我一直在使用与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

需要说的是在该查询之后计算第三列“Sum(count(id))”。此列的任何条目都是记录前的总和。 所以有一个公式,必须选择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记录。之后,命令记录该表的所有记录。

oracle
1个回答
0
投票

发帖后,我搜索过了。最后我被重定向到HERE。我可以达到对我非常兴奋的响应时间。它从3分钟减少到不到3秒。有必要知道,我只使用该站点中Duplicate constant condition for different tables whenever possible的所有查询优化指南中的一个提示。 注意:在执行此提示之前,where子句和order-by中的字段上有一些索引。

© www.soinside.com 2019 - 2024. All rights reserved.