私のチームは、SQL Server データベースを使用しているときにパフォーマンスの問題に直面し続けています。まず、アプリケーションは Java で作成され、Hibernate を使用します。完全なオブジェクト (特定のテーブルのすべてまたはほとんどのフィールドなど) を選択する場合に備えて、簡単かつスムーズに取得できるデータベースにいくつかのデータが保存されています。
これはうまく機能しますが、より小さなクエリを実行すると、10 倍遅くなります。最も明白な部分は、フィールドの小さな選択 (この例では: 3) を取得し、そこに like を含む WHERE 句を使用することです (84 フィールドを取得する場合は問題にはならないようですが、 3 つのフィールドを取得します)。
Hibernate は単純なクエリを完了するのに約 7 秒かかりますが、大きなクエリでは約 3.4 秒かかります。DbVisualizer でプレーン SQL を実行すると、複雑なクエリでは、クエリに 0.02 秒、データの送信に 0.7 秒かかります。DbVisualizer で実行される単純なクエリは、なんと 0.2 秒 (10 倍遅い) かかり、わずか 0.36 秒で送信されます (したがって、転送されるデータは少なくなります)。これは大きなクエリよりもまだ高速であると主張する人もいるかもしれませんが、Hibernate のパフォーマンスに何らかの影響があるようです。
「いまいましいものが高速に実行されるまで、フィールドを追加するだけです!」と冗談を言っていましたが、選択するフィールドと where 句の両方がユーザーによって構成されるため、それはうまくいきません。 .
84 フィールド クエリは次のようになります。
select
locateable0_.Un_ID as Un1_37_,
locateable0_.active as active37_,
locateable0_.code as code37_,
locateable0_.name as name37_,
locateable0_.ClientID as ClientID37_,
locateable0_.equipmentGroup as equipmen7_37_,
locateable0_.SupplierContractID as Supplier8_37_,
locateable0_.orderingCode as ordering9_37_,
locateable0_.expirationDate as expirat10_37_,
locateable0_.purchaseDate as purchas11_37_,
locateable0_.warrantyExpirationAlert as warrant12_37_,
locateable0_.price as price37_,
locateable0_.priceUnit as priceUnit37_,
locateable0_.VatID as VatID37_,
locateable0_.WEAlertJobID as WEAlert16_37_,
locateable0_.barcode as barcode37_,
locateable0_.erpCode as erpCode37_,
locateable0_.description as descrip19_37_,
locateable0_.innerWorksheet as innerWo20_37_,
locateable0_.outerWorksheet as outerWo21_37_,
locateable0_.ContractorCompanyID as Contrac22_37_,
locateable0_.ContractorPersonID as Contrac23_37_,
locateable0_.ManufacturerCompanyID as Manufac24_37_,
locateable0_.ManufacturerPersonID as Manufac25_37_,
locateable0_.ServicerCompanyID as Service26_37_,
locateable0_.ServicerPersonID as Service27_37_,
locateable0_.BudgetID as BudgetID37_,
locateable0_.costObjectId as costObj29_37_,
locateable0_.costKindId as costKindId37_,
locateable0_.TemplateId as TemplateId37_,
locateable0_.openingDate as opening32_37_,
locateable0_.mainClassId as mainCla33_37_,
locateable0_.pictureId as pictureId37_,
locateable0_.productType as product35_37_,
locateable0_.propertiesId as propert36_37_,
locateable0_.ParentID as ParentID37_,
locateable0_.accessDomainId as accessD38_37_,
locateable0_.orderStateType as orderSt39_37_,
locateable0_.orderEventId as orderEv40_37_,
locateable0_.locationId as locationId37_,
locateable0_.siteId as siteId37_,
locateable0_.buildingId as buildingId37_,
locateable0_.storeyId as storeyId37_,
locateable0_.roomId as roomId37_,
locateable0_.cadObjectId as cadObje46_37_,
locateable0_.geoLattitude as geoLatt47_37_,
locateable0_.geoLongitude as geoLong48_37_,
locateable0_.ratingId as ratingId37_,
locateable0_.grossArea as grossArea37_,
locateable0_.grossVolume as grossVo51_37_,
locateable0_1_.floor as floor99_,
locateable0_2_.calculatedArea as calculat2_100_,
locateable0_2_.nominalArea as nominalA3_100_,
locateable0_2_.categoryId as categoryId100_,
locateable0_2_.wingId as wingId100_,
locateable0_2_.areaUnitId as areaUnitId100_,
locateable0_2_.cleaningArea as cleaning7_100_,
locateable0_2_.rentableArea as rentable8_100_,
locateable0_2_.windowSurface as windowSu9_100_,
locateable0_2_.bottomSurface as bottomS10_100_,
locateable0_2_.topSurface as topSurface100_,
locateable0_2_.wallSurface as wallSur12_100_,
locateable0_2_.floorType as floorType100_,
locateable0_3_.areaSize as areaSize101_,
locateable0_3_.areaType as areaType101_,
locateable0_3_.flooring as flooring101_,
locateable0_4_.workplaceNumber as workplac2_102_,
locateable0_4_.workplaceType as workplac3_102_,
locateable0_4_.usingCompanyId as usingCom4_102_,
locateable0_5_.quantity as quantity190_,
locateable0_5_.quantityUnitId as quantity3_190_,
locateable0_6_.inventoryNumber as inventor2_202_,
locateable0_7_.area as area233_,
locateable0_7_.meterValue as meterValue233_,
locateable0_7_.calibrationFactor as calibrat4_233_,
locateable0_7_.areaDomainId as areaDoma5_233_,
locateable0_7_.degreeDayId as degreeDa6_233_,
locateable0_7_.virtualType as virtualT7_233_,
locateable0_7_.differenceFactor as differen8_233_,
locateable0_7_.differenceMasterId as differen9_233_,
locateable0_7_.virtual as virtual233_,
locateable0_7_.startDate as startDate233_,
locateable0_7_.scheduleId as scheduleId233_,
locateable0_.discriminator as discrimi2_37_
from
MNT_Equipments locateable0_
left outer join
Storey locateable0_1_
on locateable0_.Un_ID=locateable0_1_.id
left outer join
Room locateable0_2_
on locateable0_.Un_ID=locateable0_2_.id
left outer join
RoomArea locateable0_3_
on locateable0_.Un_ID=locateable0_3_.id
left outer join
Workplace locateable0_4_
on locateable0_.Un_ID=locateable0_4_.id
left outer join
INV_Product locateable0_5_
on locateable0_.Un_ID=locateable0_5_.id
left outer join
MNT_FacilityProduct locateable0_6_
on locateable0_.Un_ID=locateable0_6_.id
left outer join
EN_ResourceMeter locateable0_7_
on locateable0_.Un_ID=locateable0_7_.id
left outer join
DynamicProperties dynamicpro1_
on locateable0_.propertiesId=dynamicpro1_.id
left outer join
KEYWORDSEARCH tags2_
on dynamicpro1_.id=tags2_.dynamicPropertiesId
left outer join
MNT_Clients client3_
on locateable0_.ClientID=client3_.Un_ID
where
(
locateable0_.accessDomainId is null
or locateable0_.accessDomainId in (
select
uad.domainId
from
PERM_UserAccessDomain uad
join
Users u
on uad.userId = u.Un_ID
where
u.UserName = 'wsc'
and uad.functionId = 2000
)
)
and locateable0_.discriminator in (
'17000', '6010', '6020', '6030', '6035', '6040', '6060', '6070', '6080', '18000', '5010', '6000', '6100', '5000', '9000', '14000', '19000'
)
and (
client3_.Un_ID in (
1012, 1016, 1013, 1014
)
)
and (
locateable0_.productType not in (
18000, 19000
)
)
and locateable0_.active=1
and locateable0_.productType<>6080
and (
upper(tags2_.keyword) like 'B%'
)
低速の 3 フィールド クエリは次のようになります。
select
locateable0_.Un_ID as col_0_0_,
locateable0_.code as col_1_0_,
locateable0_.name as col_2_0_
from
MNT_Equipments locateable0_
left outer join
DynamicProperties dynamicpro1_
on locateable0_.propertiesId=dynamicpro1_.id
left outer join
KEYWORDSEARCH tags2_
on dynamicpro1_.id=tags2_.dynamicPropertiesId
left outer join
MNT_Clients client3_
on locateable0_.ClientID=client3_.Un_ID
where
(
locateable0_.accessDomainId is null
or locateable0_.accessDomainId in (
select
uad.domainId
from
PERM_UserAccessDomain uad
join
Users u
on uad.userId = u.Un_ID
where
u.UserName = 'wsc'
and uad.functionId = 2000
)
)
and locateable0_.discriminator in (
'17000', '6010', '6020', '6030', '6035', '6040', '6060', '6070', '6080', '18000', '5010', '6000', '6100', '5000', '9000', '14000', '19000'
)
and (
client3_.Un_ID in (
1012, 1016, 1013, 1014
)
)
and (
locateable0_.productType not in (
18000, 19000
)
)
and locateable0_.active=1
and (
upper(tags2_.keyword) like 'B%'
)
Microsoft SQL Server Management Studio は、要求されたフィールドにインデックスを追加することを提案していますが、そうしてもまったく役に立ちません。特に、クエリされるフィールドはユーザーが構成できるようになり、休止状態はクエリとフェッチにかかる時間に加えて大きなボーナスを追加することを心に留めておくと.
では、許容できるレベルまでパフォーマンスを向上させるにはどうすればよいでしょうか?