2017-07-19 12 views
1

私は、既存のクエリに左結合を追加する必要がある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 ""で置き換えて、データ自体が問題にならないようにしました。助言がありますか?

+0

だから2つのもの。 1、あなたが 'Add'を呼んでいなければ問題がありますか? 2)dr.GetString(ColumnName)の代わりにdr(ColumnName)を使用してクエリを実行してください。過剰なクエリ時間は、クエリの型をvarcharに変換する可能性があります。 –

答えて

0

このような多くの問題は、varcharの一方の側を他方のintに比較または結合する場合など、クエリで文字列に変換される型に対して行われます。

クエリは、データベース、あなたがあなたのクエリを実行しようとすると、データリーダーは次のように行を読み取った後、.NETは、あなたのデータ型変換をやらせるから直接、パフォーマンス上の問題もなく動作している場合:

Private Sub Fetch(ByVal dr As SafeDataReader) 
    Using dr 
     While dr.Read() 
     Add(InspectionDocumentSummary.GetInspectionDocumentSummary(dr)) 
     _id = GUID.Parse(dr("Id")) 
     _identificationNumber = dr("IdentificationNumber") 
     _status = dr("Status") 
     _originator = dr("Originator") 
     _dateCreated = dr.GetSmartDate("DateCreated") 
     _poPartNumber = dr("PoPartNumber") 
     _poPartRev = dr("PoPartRev") 
     _lotQuantity = Convert.ToString(dr.GetInt32("LotQuantity")) 
     _buyer = dr("Buyer") 
     _spe = dr("Spe") 
     _agencyDocId = dr("AgencyDocId") 
     _agencyName = dr("AgencyName") 
     _activity = dr("Activity") 
     _controlNumber = dr("ControlNumber") 
     _dispositioned = dr("Dispositioned") 
     _programName = dr("ProgramName") 
     _supplierEsd = dr("SupplierEsd") 
     _supplierName = dr("SupplierName") 
     _commodityCode = dr("CommodityCode") 
     End While 
    End Using 
End Sub 

それはdoesnの場合そのメソッドの何かが問題を引き起こしていないことを確認するためにAddを呼び出さずに実行してみてください。