2015-03-30 2 views
0

У меня есть следующий запрос, который выполняет левое соединение между 3 таблицами. Проблема в том, что для запуска требуется 20 секунд, даже если возвращается только несколько строк. Если я оставлю «большие поля» из таблицы предложений, запрос выполняется почти мгновенно. Таким образом, кажется, что проблема в том, что по какой-то причине sqlserver извлекает значения этих полей, прежде чем применять оператор where. Есть ли способ ускорить выполнение этого запроса?Медленное двойное левое соединение

SELECT N0."OID" 
    ,N1."FirstName" 
    ,N1."LastName" 
    ,N0."SmallField" 
    ,N0."LargeField1" 
    ,N0."LargeField2" 
FROM (
    (
     "dbo"."Offer" N0 LEFT JOIN "dbo"."Address" N1 ON (N0."OfferDeliveryAddress" = N1."OID") 
     ) LEFT JOIN "dbo"."Customer" N2 ON (N0."Customer" = N2."OID") 
    ) 
WHERE (
     N0."GCRecord" IS NULL 
     AND (
      (isnull(CharIndex('John Smith', N2."FirstName" + ' ' + N2."LastName"), 0) > 0) 
      OR (isnull(CharIndex('John Smith', N2."LastName" + ' ' + N2."FirstName"), 0) > 0) 
      OR (isnull(CharIndex('John Smith', N2."FirstName"), 0) > 0) 
      OR (isnull(CharIndex('John Smith', N2."LastName"), 0) > 0) 
      ) 
     ) 
+1

Возможно, это медленный не из-за объединений, а в ваш сложный вопрос, где статья –

+0

Не могли бы вы создать sql-скрипку, это даст людям возможность взглянуть на «образцовые» данные, план выполнения и сможет предоставить решения –

+0

Измените LEFT JOIN на клиенте в INNER JOIN, ваша WHERE CLAUSE будет исключать все, у кого нет записи в Клиенте. Попробуйте это как ваше условие: CharIndex ('John Smith', COALESCE ([N2]. [FirstName], '') + '' + COALESCE ([2]. [LastName], ''))> 0 –

ответ

1

По крайней мере, вы можете оптимизировать, где состояние следующим образом:

WHERE (
     N0."GCRecord" IS NULL 
     AND (
      (isnull(CharIndex('John Smith', N2."FirstName" + ' ' + N2."LastName"), 0) > 0) 
      OR (isnull(CharIndex('John Smith', N2."LastName" + ' ' + N2."FirstName"), 0) > 0) 
      ) 
     ) 

потому что последние два условия включены в первые два.

Под редакцией В качестве примера увидеть, почему это так:

FirstName = 'XXXJohn Smith' 
LastName = 'YYY' 

FirstName + ' ' + LastName = 'XXXJohnSmith YYY' 

так что если JohnSmith содержится в FirstName он также содержится в FirstName + ' ' + LastName

+0

'потому что последние два условия включены в первые два. Это неверно. В последних двух условиях он ищет Джона Смита только в FirstName или LastName. –

+0

Но если John Smith включен в FirstName, он также включен в FirstName + '' + LastName и тот же для LastName + '' + FirstName. В качестве примера, если FirstName является «XXXJohn SmithXXX», а lastName «YYY», поэтому FirstName + '' + LastName - это «XXXJohn SmithXXX YYY», и он содержит, как очевидно, «John Smith» –

+0

, да, вы правы. простите за это. взяв обратно мой downvote. –

0
  • Первый в выберите часть, удалив N0. «LargeField1», N. «LargeField2» имеют значение?

  • второй, в котором часть N2. «FirstName» и N2. «LastName» потенциально в неприятности из-за запросов на функции не использовал базу данных индексов

  • И, пожалуйста, проверьте ваш план выполнения.

1

Измените положение WHERE на sargable пункта:

WHERE (
     N0."GCRecord" IS NULL 
     AND (
       (N2."FirstName" LIKE 'John%' AND N2."LastName" LIKE 'Smith%') OR 
       (N2."LastName" LIKE 'John%' AND N2."FirstName" LIKE 'Smith%') OR 
       N2."FirstName" LIKE 'John Smith%' OR 
       N2."LastName" LIKE 'John Smith%' 
      ) 
     ) 

Добавить индексы в колонке FirstName и LastName. В этом случае предложение должно извлекать выгоду из этих индексов, потому что LIKE 'ABC%' является приемлемым.

+0

Это не эквивалентно тому, что задано. Здесь вы ищете FirstName, начиная с Джона. Он попросил FirstName, содержащего Джона ... и так далее. –

+0

У вас есть, по крайней мере, чтобы изменить его на следующий эквивалент WHERE ( N0. «GCRecord» IS NULL AND ( (N2. «FirstName» LIKE '% John%' AND N2. "LastName" LIKE 'Smith%') ИЛИ (N2. "LastName" LIKE '% John%' AND N2."Имя" LIKE 'Smith%') OR N2. "FirstName" LIKE '% Джон Смит%' OR N2. "LastName" LIKE '% John Smith%' ) ) –

+0

Да, но этот ответ фокусируется на оптимизация через SARG. Иначе он не будет использовать какие-либо индексы. Поэтому, если этот оператор удовлетворяет данные в базе данных, тогда лучше будет придерживаться этого утверждения. 'LIKE '% ABC%'' не будет использовать индекс. 'LIKE 'ABC%'' будет использовать индекс. Вот в чем дело. –

Смежные вопросы