2017-07-19 129 views
1

我有一個vb.net/SQL Server客戶端應用程序,我需要在其中添加左連接到現有查詢。 asp.net使用數據層中的相同代碼來檢索Web版本應用程序的數據。接下來的兩個代碼塊顯示了整個原始語句以及包含所有連接的新語句。我建議你跳到較低的代碼塊,這些代碼塊要小得多來說明問題。 原始查詢:Slow 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 

新的查詢增加了一個左連接到第二個表(qasr_metric),以確定第二個表包含爲1的值的任何關聯的行在「D」欄中。 qasr_metric表由(quasr_id,d)索引,這就是性能受到最小影響的原因。刪除所有其他列,並加入歸結之間的區別:

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 

上的應用程序的asp.net側新的查詢的性能大約3秒內原始查詢,如果我在SQL Server Mgmt Studio中單獨運行查詢,情況也是如此。但是,應用程序的客戶端在幾秒鐘內處理原始查詢的結果,但對於新查詢需要一個多小時,這很荒唐。查看vb代碼本身,數據層使用參數化查詢調用ExecuteReader,對於原始查詢和新查詢都幾乎立即完成。問題發生在由dr作爲由ExecuteReader填充的閱讀器調用的業務層中。每行中返回的數據用於填充新對象(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

所以有兩件事。 1,如果你沒有調用'Add',是否有問題? 2)使用dr(ColumnName)而不是dr.GetString(ColumnName)嘗試查詢,因爲可能過多的查詢時間是由於在查詢中將類型轉換爲varchar。 –

回答

0

像這樣的許多問題都是爲了在查詢中將字符串轉換爲字符串,例如比較或將varchar one one side與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 

如果沒有按無需撥打Add來幫助嘗試運行它,以確保該方法中的某些內容不會導致問題。