2012-07-12 4 views
3

나는 최적화 할이 쿼리를최적화

SET ANSI_NULLS ON 
GO 
SET QUOTED_IDENTIFIER ON 
GO 
ALTER PROCEDURE [dbo].[ComprobantesFacturasObtenerEstadisticasLocal2] 
(
    @FechaDesde DateTime, 
    @FechaHasta DateTime, 
    @XML ntext 
) 
AS 
BEGIN 

    DECLARE @docHandler INT 

    EXEC sp_xml_preparedocument @docHandler OUTPUT, @XML  

    --Locales 
    Select IdLocal 
    into #seleccionados 
    FROM OPENXML(@docHandler, N'/NewDataSet/Table1', 2) 
    WITH (IdLocal int) 

    select d.* into #Locales from Dim_Sucursal d inner join GrimRepCen..Locales l on l.Codigo = d.Codigo inner join #seleccionados s on s.IdLocal = l.iDlocal 

    /*2011/12/06 busco los descuentos del rio*/ 
    select distinct l.Codigo + ' - ' + l.Nombre as local, c.IdComprobante, -1 as Cantidad, 
     -1 * isnull(abs(c.TotalNeto),0) as IMPORTE, 
     'Varios' as Familia, 'Dto Bco Rio' as Linea 
    into #descuentoRio 
    from Fact_Comprobante(nolock) c 
    --inner join Fact_ComprobanteItem(nolock) ci on ci.IdComprobante = c.IdComprobante 
    inner join #locales l on c.idDim_ComprobanteTipo = 5 and l.IdDim_sucursal = c.IdDim_sucursal and c.fecha between @FechaDesde and @FechaHasta 

    /*******************COMPROBANTES************************************************ */ 
    select distinct 
     c.*, l.Codigo + ' - ' + l.Nombre as local, ct.IdComprobanteTipo 
    into #Comprobantes 
    from Fact_Comprobante(nolock) c 
    inner join Fact_ComprobanteItem(nolock) ci on ci.IdCOmprobante = c.IdComprobante 
    inner join Dim_ComprobanteTipo(nolock) ct on ct.IdDim_ComprobanteTipo = c.idDim_ComprobanteTipo 
    inner join #locales l on l.IdDim_sucursal = c.IdDim_sucursal and ct.IdComprobanteTipo not in (46 /*Error Fiscal Factura B*/, 47 /*Error Fiscal Factura A*/) and c.fecha between @FechaDesde and @FechaHasta 

    --Comprobantes por Linea/Marca/Familia 
    select 
     m.Nombre as Marca, l.Nombre as Linea , case when c.IdComprobanteTipo in (21,23,26,28) then 0 else -sum(ci.Cantidad) end as Cantidad, 
     case when c.IdComprobanteTipo in (21,23,26,28) 

     --toma en cuenta los descuentos de las facturas que fueron anuladas 
     then c.TotalNeto 
     else isnull(ci.ImporteNeto,0) - isnull((select sum(importe) as importe 
               from Fact_Descuento (nolock) DD 
               where DD.IdComprobante = ci.idComprobante and ci.IdDim_Producto = IdDim_Producto 
               and ci.IdDim_Medida = IdDim_Medida and ci.IdDim_Calidad = IdDim_Calidad 
               and exists 
                (
                 select 1 
                 from ComprobanteReferencias AA 
                 inner join Fact_Comprobante BB on aa.IdComprobanteCredito = BB.IdComprobante 
                 where AA.IdComprobanteDebito = DD.IdComprobante 
                 and BB.IdDim_ComprobanteTipo in (4,13,16,19) 
                ) 
               ),0) 
     end as IMPORTE, 
     f.Nombre as Familia 
    from #Comprobantes c 
    inner join Fact_ComprobanteItem(nolock) ci on ci.IdComprobante = c.IdComprobante 
    inner join Dim_Producto(nolock) p on p.IdDim_Producto = ci.IdDim_Producto 
    inner join Dim_Marca(nolock) m on m.IdDim_Marca = p.IDDim_Marca 
    inner join Dim_Familia(nolock) f on f.idDim_Familia = p.IdDim_Familia 
    inner join Dim_Linea(nolock) l on l.IdDim_Linea = p.IdDim_Linea 
    Group by m.Nombre,l.Nombre,f.Nombre,c.TotalNeto,ci.IdComprobante, ci.IdDim_producto, 
    ci.idDim_Medida,ci.ImporteNeto,c.IdComprobanteTipo ,ci.IdDim_Calidad 
    union all 
    select 'Grimoldi' as Marca, Linea , - 1 Cantidad, 
     IMPORTE, 
     Familia 
    from #descuentoRio 

    --/*Familia*/ 
    select case when c.IdComprobanteTipo in (21,23,26,28) then 0 else -isnull(sum(ci.Cantidad),0) end as Cantidad, 
    case when c.IdComprobanteTipo in (21,23,26,28) 

     --toma en cuenta los descuentos de las facturas que fueron anuladas 
     then c.TotalNeto 
     else isnull(ci.ImporteNeto,0) - isnull((select sum(importe) as importe 
               from Fact_Descuento (nolock) DD 
               where DD.IdComprobante = ci.idComprobante and ci.IdDim_Producto = IdDim_Producto 
               and ci.IdDim_Medida = IdDim_Medida and ci.IdDim_Calidad = IdDim_Calidad 
               and exists 
                (
                 select 1 
                 from ComprobanteReferencias AA 
                 inner join Fact_Comprobante BB on aa.IdComprobanteCredito = BB.IdComprobante 
                 where AA.IdComprobanteDebito = DD.IdComprobante 
                 and BB.IdDim_ComprobanteTipo in (4,13,16,19) 
                ) 
               ),0) 
     end as IMPORTE, 
     f.Nombre as Familia 
    from #Comprobantes c 
    inner join Comprobantes(nolock) co on co.IdComprobante = c.IdComprobante 
    inner join Fact_ComprobanteItem(nolock) ci on ci.IdComprobante = c.IdComprobante 
    inner join Dim_Producto(nolock) p on p.IdDim_Producto = ci.IdDim_Producto 
    full outer join Dim_Familia(nolock) f on f.idDim_Familia = p.IdDim_Familia 
    Group by f.Nombre,ci.ImporteNeto,ci.IdComprobante, ci.IdDim_producto, 
    ci.idDim_Medida,c.TotalNeto, c.IdComprobanteTipo ,ci.IdDim_Calidad 
    union all 
    select -1 as Cantidad, 
     IMPORTE, 
     Familia 
    from #descuentoRio 

    /*local*/ 
    select c.Local, case when c.IdComprobanteTipo in (21,23,26,28) then 0 else -isnull((sum(ci.Cantidad)),0) end as Cantidad, 
     case when c.IdComprobanteTipo in (21,23,26,28) 

     --toma en cuenta los descuentos de las facturas que fueron anuladas 
     then c.TotalNeto 
     else isnull(ci.ImporteNeto,0) - isnull((select sum(importe) as importe 
               from Fact_Descuento (nolock) DD 
               where DD.IdComprobante = ci.idComprobante and ci.IdDim_Producto = IdDim_Producto 
               and ci.IdDim_Medida = IdDim_Medida and ci.IdDim_Calidad = IdDim_Calidad 
               and exists 
                (
                 select 1 
                 from ComprobanteReferencias AA 
                 inner join Fact_Comprobante BB on aa.IdComprobanteCredito = BB.IdComprobante 
                 where AA.IdComprobanteDebito = DD.IdComprobante 
                 and BB.IdDim_ComprobanteTipo in (4,13,16,19) 
                ) 
               ),0) 
    end as IMPORTE, 
    f.Nombre as Familia, l.Nombre as Linea 
    from #Comprobantes c 
    inner join Comprobantes(nolock) co on co.IdComprobante = c.IdComprobante 
    inner join Fact_ComprobanteItem(nolock) ci on ci.IdComprobante = c.IdComprobante 
    inner join Dim_Producto(nolock) p on p.IdDim_Producto = ci.IdDim_Producto 
    inner join Dim_Linea(nolock) l on l.IdDim_Linea = p.IdDim_Linea 
    inner join Dim_Familia(nolock) f on f.idDim_Familia = p.IdDim_Familia 
    Group by f.Nombre,ci.ImporteNeto, l.Nombre ,ci.IdComprobante, ci.IdDim_producto, 
    ci.idDim_Medida, c.Local,c.TotalNeto, c.IdComprobanteTipo,ci.IdDim_Calidad 
    union all 
    select Local, -1 as Cantidad, 
     IMPORTE, 
     Familia, Linea 
    from #descuentoRio 
end 

어떤 내가 다른 방법 대신 XML의 id의를 전송, 예를 들어, 변경할 수 없습니다 것을 (I 때문에이있다 코드를 수정해야만 할 수 있습니다.), 테이블 및 기타 물건의 구조. 나는 단지 이것을 저장할 수있다. 이 쿼리는 일부 ID를 수신하고 임시 테이블 (#Seleccionados)에 삽입하고 일부 조인을 사용하여 영업 및 기타 정보를 얻습니다. 또한 이상한 일, harcoded 값이있는 Union ALL 및 다른 것들을 볼 수 있습니다. 그 이유는 코드의 보고서가 수행 된 방식과이를 변경할 수 없기 때문입니다. (이상한 일은 걱정하지 않아도됩니다.) 이것은 기본적으로 4 개의 선택을 반환합니다. 그 중 하나는 단지 하나의 행이므로 다른 3 개에 문제가있어 여기서 보여 드리겠습니다.

나는 시도했다 : 반복되는 ISNULL 절에

(select sum(importe) as importe 
               from Fact_Descuento (nolock) DD 
               where DD.IdComprobante = ci.idComprobante and ci.IdDim_Producto = IdDim_Producto 
               and ci.IdDim_Medida = IdDim_Medida and ci.IdDim_Calidad = IdDim_Calidad 
               and exists 
                (
                 select 1 
                 from ComprobanteReferencias AA 
                 inner join Fact_Comprobante BB on aa.IdComprobanteCredito = BB.IdComprobante 
                 where AA.IdComprobanteDebito = DD.IdComprobante 
                 and BB.IdDim_ComprobanteTipo in (4,13,16,19) 
                ) 
               ) 

: 예를 들어, repetead 몇 가지 일을 해결하기 위해,이 하위 쿼리를 시도했다 내가 생각

3이 선택됩니다. 그래서, 나는 Common_Expresion_Table WITH을 사용하여 그것을 줄일 수 있다고 생각합니다. 하지만, 하위 쿼리를 사용할 때 하위 쿼리를 사용할 때 선택 항목의 값에 따라 선택 항목이 달라집니다 (하위 쿼리의 where 절에서 볼 수 있음)

그렇다면 3 개가 있습니다. 별로 다르지 않습니다. 그들은 조인을 몇 번 반복했지만 다른 방식으로 그룹화했습니다. 그래서, 나는 또한 시간적으로 테이블 또는 CTE의 어떤 종류를 사용하는 thougt,하지만 그들은 다른 방법에서 그룹화되어 있기 때문에 그것에 대해 확실하지 않다, 또한 하나 또는 두 개의 differents의 JOINS

일부 추가 정보가 있습니다

#Seleccionados에는 100 개의 ID 행이 있습니다. 이 쿼리에는 50 개의 seg가 필요합니다. 일주일의 경우 :

  • 첫 번째 쿼리는 거의별로 그룹화 동일한 정보,의, 두 번째 질의는 당신이 볼 수있는 세 번째 쿼리가 47084 rows

반환 47084 rows

  • 반환 47083 rows
  • 반환 다른 방법.

    테이블 : Fact_Comprobante 한 판매에 대한 정보가 있습니다. Fact_ComprobanteItem 판매 항목에 대해. Dim_Producto 제품에 대한 정보, Dim_Familia 정보 제품군 Dim_Marca은 Signs of products에 대한 정보를 가지고 있습니다. Dim_Linea은 라인 제품에 대한 정보를 가지고 있습니다. (이 3 개의 테이블은 Dim_Producto에서 FK입니다.) Dim_ComprobanteTipo 판매 유형에 대한 정보를 얻었습니다 Fact_Descuento 판매에 관련된 할인 정보가 있습니다.

    모든 테이블에는 많은 정보가 있습니다.

    (Nolock) 진술은이 테이블에서 동시에 3 개의 서비스가 삽입, 업데이트 및 기타 서비스가 있기 때문입니다.

    이 쿼리를 수행하지 않았으므로 최적화해야합니다.

  • 답변

    0

    SQL 프로파일 러 (액세스 할 수있는 경우)를 사용하고 저장 프로 시저의 이름을 필터링하십시오. 모든 단계를 표시하는지 확인하십시오 (프로 시저를 실행하면 1 또는 2 행 이상이 제공됩니다). 그런 다음 매 단계마다 nr 초, nr의 읽기, 쓰기 등을 볼 수 있습니다. 그러면 시간 소모적 인 부분에 집중할 수 있습니다.

    아마 고가의 하나입니다 ... 나는 부질 에서 시작 ( 존재하는 것이다 절차에 다이빙없이

    declare @dStart datetime 
    set @dStart = getdate() 
    
    -- at every place you like to monitor 
    print 'a: ' + convert(nvarchar(datediff(ms, @dStart, getdate())) 
    

    :

    대안이 SQL 프로파일 링 대안을 사용할 수 있습니다 , 오히려 왼쪽 또는 오른쪽 조인에 그걸 다시 작성

    +0

    답변을 주셔서 감사합니다! 나는 최근에 저장을 수정했고, 지금은 20segs 더 빠릅니다. 나는 첫 번째와 세 번째 sele ct를 입력 한 다음 다른 필드별로 그룹화를 선택하십시오. 나는 ISNULL 문을 수정해야한다는 것을 알고 있지만 어떻게해야할지 모르겠다. 바로 지금, 더 이상 돈이 없습니다 (예산은 미안 해요, 영어는 나쁜 것입니다). 그래서 나중에 보게 될 것입니다. –