私は、既存のクエリに左結合を追加する必要があるvb.net/SQL Serverクライアントアプリケーションを持っています。データレイヤー内のこの同じコードは、asp.netによってアプリケーションのWebバージョンのデータを取得するために使用されます。次の2つのコードブロックは、元の文全体と新しい文をすべての結合で示します。私はあなたが問題を説明するためにはるかに小さい下のコードブロックにスキップすることをお勧めします。 元のクエリ:遅いSafeDataReaderループ
select q.qasr_id as Id,
q.qasr_identification_number as IdentificationNumber,
q.status as Status,
b.business_unit_name as BusinessUnitName,
b.business_unit_id as BusinessUnitId,
u.login as Originator,
q.date_created as DateCreated,
q.po_number as PoNumber,
q.po_part_number as PoPartNumber,
q.po_part_rev as PoPartRev,
q.lot_quantity as LotQuantity,
q.control_number as ControlNumber,
q.item_number as PoItem,
q.buyer as Buyer,
q.buyercode as BuyerCode,
q.spe as Spe,
p.program as ProgramName,
l.product_line as productline,
s.ent_supplier_nbr as SupplierEsd,
s.sup_name1 as SupplierName,
c.commodity_code as CommodityCode,
a.agency_name as AgencyName,
q.verifyid as AgencyDocId,
q.activity as Activity,
case q.isdeleted when 1 then 'Deleted' else '' end as Deleted
from qasr q
join auth_user u on q.auth_user_id = u.auth_user_id
join functional_area f on q.functional_area_id = f.functional_area_id
join business_unit b on f.business_unit_id = b.business_unit_id
left join suppliers s on q.supplier_id = s.supplier_id
left join programs p on q.program_id = p.program_id
left join product_lines l on p.product_line_id = l.product_line_id
left join commodities c on q.commodity_id = c.commodity_id
left join agency a on q.agency_id = a.agency_id
where b.business_unit_id = @BusinessUnitId
and q.isdeleted = @IsDeleted
新しいクエリ:
select q.qasr_id as Id,
q.qasr_identification_number as IdentificationNumber,
q.status as Status,
b.business_unit_name as BusinessUnitName,
b.business_unit_id as BusinessUnitId,
u.login as Originator,
q.date_created as DateCreated,
q.po_number as PoNumber,
q.po_part_number as PoPartNumber,
q.po_part_rev as PoPartRev,
q.lot_quantity as LotQuantity,
q.control_number as ControlNumber,
q.item_number as PoItem,
q.buyer as Buyer,
q.buyercode as BuyerCode,
q.spe as Spe,
p.program as ProgramName,
l.product_line as productline,
s.ent_supplier_nbr as SupplierEsd,
s.sup_name1 as SupplierName,
c.commodity_code as CommodityCode,
a.agency_name as AgencyName,
q.verifyid as AgencyDocId,
q.activity as Activity,
case q.isdeleted when 1 then 'Deleted' else '' end as Deleted,
case when m.d_count > 0 then 'Yes' else 'No' end as Dispositioned
from qasr q
join auth_user u on q.auth_user_id = u.auth_user_id
join functional_area f on q.functional_area_id = f.functional_area_id
join business_unit b on f.business_unit_id = b.business_unit_id
left join suppliers s on q.supplier_id = s.supplier_id
left join programs p on q.program_id = p.program_id
left join product_lines l on p.product_line_id = l.product_line_id
left join commodities c on q.commodity_id = c.commodity_id
left join agency a on q.agency_id = a.agency_id
left join (select qasr_id as qasr_id, count(1) as d_count
from qasr_metric
where d = 1
group by qasr_id) m on m.qasr_id = q.qasr_id
where b.business_unit_id = @BusinessUnitId
and q.isdeleted = @IsDeleted
新しいクエリは、左が第二の表は、1の値を持つ任意の関連する行が含まれているかどうかを判断するために、第2のテーブル(qasr_metric)に参加追加します列 "D"に表示されます。 qasr_metricテーブルは(quasr_id、d)でインデックス付けされます。そのため、パフォーマンスにはほとんど影響しません。アプリのasp.net側で新しいクエリのパフォーマンスが約3秒以内で
select q.qasr_id as Id from qasr q
と
select q.qasr_id as Id,
case when m.d_count > 0 then 'Yes' else 'No' end as Dispositioned
from qasr q
left join (select qasr_id as qasr_id, count(1) as d_count
from qasr_metric
where d = 1
group by qasr_id) m on m.qasr_id = q.qasr_id
:他のすべての列を削除し、参加することとの間の差に帰着しますSQL Server Mgmt Studioでクエリを個別に実行すると、元のクエリと同じクエリが実行されます。しかし、アプリケーションのクライアント側では、元のクエリの結果は数秒で処理されますが、新しいクエリでは1時間以上かかるため、不合理です。 vbコードそのものを見ると、データレイヤーはパラメータ付きクエリでExecuteReaderを呼び出すため、元のクエリーと新しいクエリーの両方に対してほぼ即座に完了します。この問題は、ExecuteReaderによって読み込まれたリーダーとしてdrで呼び出されるビジネスレイヤーに戻って発生します。各行に返されるデータは、新しいオブジェクト(InspectionDocumentSummary)を設定するために使用され、これらのオブジェクトのリストは、ユーザーに表示されるDataGridViewにデータを格納するために使用されます。簡潔にするために新しいオブジェクトを作成潜水艦のいくつかを組み合わせることで得られます。元のクエリのために
Private Sub Fetch(ByVal dr As SafeDataReader)
Using dr
While dr.Read()
Add(InspectionDocumentSummary.GetInspectionDocumentSummary(dr))
_id = dr.GetGuid("Id")
_identificationNumber = dr.GetString("IdentificationNumber")
_status = dr.GetString("Status")
_originator = dr.GetString("Originator")
_dateCreated = dr.GetSmartDate("DateCreated")
_poPartNumber = dr.GetString("PoPartNumber")
_poPartRev = dr.GetString("PoPartRev")
_lotQuantity = Convert.ToString(dr.GetInt32("LotQuantity"))
_buyer = dr.GetString("Buyer")
_spe = dr.GetString("Spe")
_agencyDocId = dr.GetString("AgencyDocId")
_agencyName = dr.GetString("AgencyName")
_activity = dr.GetString("Activity")
_controlNumber = dr.GetString("ControlNumber")
_dispositioned = dr.GetString("Dispositioned")
_programName = dr.GetString("ProgramName")
_supplierEsd = dr.GetString("SupplierEsd")
_supplierName = dr.GetString("SupplierName")
_commodityCode = dr.GetString("CommodityCode")
End While
End Using
End Sub
、これはほとんどすぐに完了しますが、新しいクエリは時間を引き継ぎます。 ExecuteReaderがデータを取得し、dr.ReadループがDataGridViewに返されたデータを単に読み込むことがわかりました(私の場合は他のデータ処理はありません)。上記のコードの "_dispositioned = dr.GetString(" Dispositioned ")"を "_dispositioned =" Yes ""で置き換えて、データ自体が問題にならないようにしました。助言がありますか?
だから2つのもの。 1、あなたが 'Add'を呼んでいなければ問題がありますか? 2)dr.GetString(ColumnName)の代わりにdr(ColumnName)を使用してクエリを実行してください。過剰なクエリ時間は、クエリの型をvarcharに変換する可能性があります。 –