Поле выбора SQL вызывает серьезную проблему с производительностью - PullRequest
3 голосов
/ 24 июня 2011

У меня есть хранимая процедура, которая объединяет многочисленные таблицы и выбирает из них поля.Одна из таблиц является временной таблицей.

SELECT
    a.Field1,
    a.Field2,
    b.Field3,
    b.Field4,
    c.Field5
FROM table1 a
    LEFT JOIN #table2 b ON a.Field1 = b.Field1
    INNER JOIN table3 c ON a.Field1 = c.Field1

Вышеприведенное занимает 10+ минут, однако, если я закомментирую два поля b из выбора, оставляя соединение на месте, оно запускается всего за несколько секунд.

У меня естьвытащил это из процедуры для упрощения и того же поведения.Также планы выполнения почти идентичны.

Любая помощь приветствуется.

Ответы [ 5 ]

1 голос
/ 24 июня 2011

Сколько строк находится во временной таблице, и является ли "Field2" во временной таблице первичным ключом?

Если вы не выбираете какие-либо строки в правой таблице левого объединения, и соединение относится к первичному ключу (или, возможно, уникальному ключу), и вы не ссылаетесь ни на какие столбцы из правой таблицы, SQL Server может избежать необходимость доступа к временной таблице вообще (поскольку наличие или отсутствие соединяющей строки не влияет на конечный результат):

Пример. Настройка стола:

create table T1 (
    ID int not null primary key,
    Col1 varchar(10) not null
)
go
insert into T1 (ID,Col1)
select 1,'a' union all
select 2,'b' union all
select 3,'c'
go
create table #t2 (
    ID int not null primary key,
    Col2 varchar(10) not null
)
go
insert into #t2 (ID,Col2)
select 1,'d' union all
select 2,'e' union all
select 4,'f'
go
create table #t3 (
    ID int not null,
    Col3 varchar(10) not null
)
go
insert into #t3 (ID,Col3)
select 1,'d' union all
select 2,'e' union all
select 1,'f'

И запросы:

select T1.ID,T1.Col1 from T1 left join #t2 t2 on T1.ID = t2.ID
select T1.ID,T1.Col1,t2.Col2 from T1 left join #t2 t2 on T1.ID = t2.ID
select T1.ID,T1.Col1 from T1 left join #t3 t3 on T1.ID = t3.ID
select T1.ID,T1.Col1,t3.Col2 from T1 left join #t2 t3 on T1.ID = t3.ID

Во всех запросах, кроме первого, соединение происходит, как и ожидалось. Но поскольку наличие или отсутствие строк в #t2 не может повлиять на конечный результат для первого запроса, оно полностью исключает выполнение объединения.

Но если это не что-то подобное (и я ожидал бы, что это будет явной разницей в планах запросов) <Я @ немного озадачен. </p>

1 голос
/ 24 июня 2011

Вы пытались перевернуть соединения?(хотя в примере запроса отсутствует условие соединения для таблицы c)

SELECT
    a.Field1,
    a.Field2,
    b.Field3,
    b.Field4,
    c.Field5
FROM table1 a
    INNER JOIN table3 c
    LEFT JOIN #table2 b ON a.Field1 = b.Field1
0 голосов
/ 24 июня 2011
select * into #temp from table1
select * into #temp1 from table2
select * into #temp2 from table3


SELECT
    a.Field1,
    a.Field2,
    b.Field3,
    b.Field4,
    c.Field5
FROM #temp a
    LEFT JOIN #temp1 b ON a.Field1 = b.Field1
    INNER JOIN #temp2 c ON a.Field1 = c.Field1



if(Object_Id('TempDB..#temp') Is Not Null)
Begin
    Drop table #temp
End
if(Object_Id('TempDB..#temp1') Is Not Null)
Begin
    Drop table #temp1
End
if(Object_Id('TempDB..#temp2') Is Not Null)
Begin
    Drop table #temp2
End
0 голосов
/ 24 июня 2011

Как насчет выполнения запроса в двух частях.Сделайте первую часть максимально ограниченной, а затем только внешнее соединение в фильтрованном множестве.

SELECT    a.Field1,   
          a.Field2,    
          b.Field3,       
          c.Field5
INTO #t
FROM table1 a   
    INNER JOIN table3 c ON a.Field1 = c.Field1

SELECT t.Field1,
       t.field2,
       b.field3,
       b.field4,
       t.field5
FROM #t t
     LEFT OUTER JOIN #table2 b ON t.Field1 = b.Field1            
0 голосов
/ 24 июня 2011

Я бы попробовал добавить индекс с включенными столбцами в #table2 и посмотреть, поможет ли это:

CREATE NONCLUSTERED INDEX IX_table2
    ON #table2 (Field1)
    INCLUDE (Field3, Field4);
...