我怎样才能优化这个SQL查询?

时间:2013-01-15 14:18:18

标签: sql sql-server sql-server-2008 query-optimization

现在我有了这个,它可以检索大约16K的记录:

DECLARE @LINE_ID INT
SET @LINE_ID = 37
SELECT 
    a.eventType as 'evento', 
    a.tipo as 'tipo', 
    a.nroSoldadura as 'nro soldadura', 
    a.cuentaOdometrica as 'Distancia Absoluta [m]',
    a.x as 'x', 
    a.y as 'y', 
    a.z as 'z', 
    a.zonaGeografica as 'Zona geografica', 
    a.orientacionSoldadura as 'orientacion', 
    a.prof * 100 as 'prof maxima [%]',
    a.longitud as 'long. [mm]',
    a.ancho as 'ancho [mm]',
    a.IntExt as 'INT o EXT',
    a.cluster as 'Cluster',
    a.espesorPared as 'espesor de pared nominal',
    a.longitudEfectiva as 'longitud efectiva',
    a.anchoEfectivo as 'Ancho efectivo',
    a.areaEfectiva as 'Area efectiva',
    a.factorSeguridad as 'Factor de seguridad',
    a.MAOP as 'MAOP (kPa)',
    a.ruptura as 'Ruptura 0.85dL (kPa)',
    a.FER as 'FER',
    NULL as 'Diametro maximo',
    NULL as 'Diametro minimo',
    NULL as 'Ovalizacion',
    NULL as 'Ovalizacion axial',
    a.orientacionSoldadura as 'Orientacion soldadura',
    a.velocidadHerramienta as 'Velc Herr',
    a.comentarios as 'comentarios'
FROM ILI_IMPORT_MFL as a
JOIN ILI_INSPECTION as b ON a.ILI_INSPECTION_ID = b.ILI_INSPECTION_ID
WHERE 
    a.ID IN (
        SELECT TOP 1 c.ID
        FROM ILI_IMPORT_MFL as c 
        JOIN ILI_INSPECTION as d ON c.ILI_INSPECTION_ID = d.ILI_INSPECTION_ID
        WHERE a.nroSoldadura = c.nroSoldadura
            AND d.LINE_ID = @LINE_ID
        ORDER BY d.BEGIN_DATE 
    )
    AND b.LINE_ID = @LINE_ID
ORDER BY a.nroSoldadura, b.BEGIN_DATE 

ILI_IMPORT_MFL和ILI_INSPECTION之间的连接就在那里,因为ILI_INSPECTION包含我需要的日期和行ID。
现在,由于子查询,此查询大约需要6分钟才能执行。子查询在那里,因为每个nroSoldadura可能有多行,我只想要它们中最老的一行。

我正在使用SQL Server 2008.
我怎么能解决这个问题?谢谢。

编辑:尝试将索引添加到nroSoldadura和BEGIN_DATE列,并将查询时间缩短到30秒。仍然很高兴看到可能的优化以便学习。

2 个答案:

答案 0 :(得分:1)

您可以尝试使用ROW_NUMBER() ... PARTITION BY替换子查询:

DECLARE @LINE_ID INT
SET @LINE_ID = 37
SELECT 
    a.eventType as 'evento', 
    a.tipo as 'tipo', 
    a.nroSoldadura as 'nro soldadura', 
    a.cuentaOdometrica as 'Distancia Absoluta [m]',
    a.x as 'x', 
    a.y as 'y', 
    a.z as 'z', 
    a.zonaGeografica as 'Zona geografica', 
    a.orientacionSoldadura as 'orientacion', 
    a.prof * 100 as 'prof maxima [%]',
    a.longitud as 'long. [mm]',
    a.ancho as 'ancho [mm]',
    a.IntExt as 'INT o EXT',
    a.cluster as 'Cluster',
    a.espesorPared as 'espesor de pared nominal',
    a.longitudEfectiva as 'longitud efectiva',
    a.anchoEfectivo as 'Ancho efectivo',
    a.areaEfectiva as 'Area efectiva',
    a.factorSeguridad as 'Factor de seguridad',
    a.MAOP as 'MAOP (kPa)',
    a.ruptura as 'Ruptura 0.85dL (kPa)',
    a.FER as 'FER',
    NULL as 'Diametro maximo',
    NULL as 'Diametro minimo',
    NULL as 'Ovalizacion',
    NULL as 'Ovalizacion axial',
    a.orientacionSoldadura as 'Orientacion soldadura',
    a.velocidadHerramienta as 'Velc Herr',
    a.comentarios as 'comentarios'
    ROW_NUMBER() OVER (PARTITION BY a.ID ORDER BY d.BEGIN_DATE) As row
FROM ILI_IMPORT_MFL as a
JOIN ILI_INSPECTION as b ON a.ILI_INSPECTION_ID = b.ILI_INSPECTION_ID
WHERE 
    row = 1
    AND b.LINE_ID = @LINE_ID
ORDER BY a.nroSoldadura, b.BEGIN_DATE 

答案 1 :(得分:0)

您想使用row_number()。您需要将其放在子查询中。我想这就是你想要的:

select * from (
SELECT 
    a.eventType as 'evento', 
    a.tipo as 'tipo', 
    a.nroSoldadura as 'nro soldadura', 
    a.cuentaOdometrica as 'Distancia Absoluta [m]',
    a.x as 'x', 
    a.y as 'y', 
    a.z as 'z', 
    a.zonaGeografica as 'Zona geografica', 
    a.orientacionSoldadura as 'orientacion', 
    a.prof * 100 as 'prof maxima [%]',
    a.longitud as 'long. [mm]',
    a.ancho as 'ancho [mm]',
    a.IntExt as 'INT o EXT',
    a.cluster as 'Cluster',
    a.espesorPared as 'espesor de pared nominal',
    a.longitudEfectiva as 'longitud efectiva',
    a.anchoEfectivo as 'Ancho efectivo',
    a.areaEfectiva as 'Area efectiva',
    a.factorSeguridad as 'Factor de seguridad',
    a.MAOP as 'MAOP (kPa)',
    a.ruptura as 'Ruptura 0.85dL (kPa)',
    a.FER as 'FER',
    NULL as 'Diametro maximo',
    NULL as 'Diametro minimo',
    NULL as 'Ovalizacion',
    NULL as 'Ovalizacion axial',
    a.orientacionSoldadura as 'Orientacion soldadura',
    a.velocidadHerramienta as 'Velc Herr',
    a.comentarios as 'comentarios',
    ROW_NUMBER() over (partition by a.nroSoldadura order by begin_date desc) as seqnum
FROM ILI_IMPORT_MFL as a
JOIN ILI_INSPECTION as b ON a.ILI_INSPECTION_ID = b.ILI_INSPECTION_ID
where b.line_id = @line_id
)
where seqnum = 1