2014-11-13 3 views
0

У меня есть несколько таблиц в базе данных. Таблица с объектами с именем ObjectTbl и таблицей с типами с именем TypesTbl.Производительность запроса на сервере Sql

Thats выглядит следующим образом:

ObjectTbl       TypesTbl 

objId | TypeId | objName |  typeId | typeName | 
-------------------------------- ---------------------- 
intObjId | typeId | objName |  intTypeId | typeName | 

TypeId столбец в таблице ObjectTbl является внешним ключом от TypesTbl. TypesTbl содержит ~ 200 записей, ObjectTbl ~ +1000000

Когда я выполнить запрос:

SELECT * FROM ObjectTbl obj 
join TypesTbl t ON t.typeName='Type_Name' 
WHERE obj.TypeId=t.typeId and (obj.objName like '%expression%' or obj.objName like '%expression2%' or obj.objName like '%expression3%') 

Это работает более 10 секунд. Но когда я использую:

declare @typeId int 

set @typeId=(select typeId from TypesTbl where typeName='Type_Name') 

SELECT * FROM ObjectTbl obj 
WHERE [email protected] and (obj.objName like '%expression%' or obj.objName like '%expression2%' or obj.objName like '%expression3%') 

Thats работает менее 1 секунды. Может ли кто-нибудь объяснить мне, почему так?

+3

Ваши индексы? что скажет ваш запрос? Это даст вам хорошую подсказку. – paqogomez

+0

Спасибо. В таблице ObjectTbl у меня есть некластеризованный индекс для столбцов objectId и TypeId. – Gleb

+1

Но ничего в 'TypeTbl'? Посмотрите на свой план запроса, найдите места, где он говорит такие неприятные вещи, как «Сканирование таблицы», и разместите там индекс. – paqogomez

ответ

1

enter image description here

SELECT * 
FROM ObjectTbl obj 
     INNER JOIN TypesTbl t ON obj.TypeId = t.typeId 
          AND t.typeName = 'Type_Name' 
WHERE (obj.objName LIKE '%expression%' 
      OR obj.objName LIKE '%expression2%' 
      OR obj.objName LIKE '%expression3%' 
     ) 
+0

Я сомневаюсь, что это создаст другой план выполнения. – Magnus

+1

Я думаю, что план выполнения будет изменен, в настоящее время он выглядит как перекрестное соединение, потому что там, где условие работает после условия соединения. – Vasily

+0

Да, это похоже на перекрестное соединение, но, скорее всего, будет обработано как внутреннее соединение с помощью механизма запросов. Посмотрите на следующий пример: http://s7.postimg.org/s3a6tyad7/sql.png – Magnus

0

Проблема заключается в том, что это действительно большой присоединиться

SELECT * 
    FROM ObjectTbl obj 
    join TypesTbl t 
    ON t.typeName = 'Type_Name' 

условия перемещения вверх в джойн поэтому оптимизатор запросов может фильтровать раньше

SELECT * 
    FROM ObjectTbl obj 
    join TypesTbl t 
    on obj.TypeId = t.typeId 
    and t.typeName = 'Type_Name' 
    and ( obj.objName like '%expression%' 
     or obj.objName like '%expression2%' 
     or obj.objName like '%expression3%') 
0
--try this 
--a) variant with CTE 

; 
WITH t AS (SELECT * 
       FROM  TypesTbl 
       WHERE typeName = 'Type_Name' 
      ) 
    SELECT * 
    FROM ObjectTbl obj 
      INNER JOIN t ON obj.TypeId = t.typeId 
    WHERE (obj.objName LIKE '%expression%' 
       OR obj.objName LIKE '%expression2%' 
       OR obj.objName LIKE '%expression3%' 
      ) 

--b) variant with #temp table 

IF OBJECT_ID('Tempdb..#t') IS NOT NULL 
BEGIN 
    DROP TABLE #t 
END 

SELECT * 
INTO #t 
FROM TypesTbl 
WHERE typeName = 'Type_Name' 

SELECT * 
FROM ObjectTbl obj 
     INNER JOIN #t AS t ON obj.TypeId = t.typeId 
WHERE (obj.objName LIKE '%expression%' 
      OR obj.objName LIKE '%expression2%' 
      OR obj.objName LIKE '%expression3%' 
     ) 

- -также вы можете попробовать внутреннее хеш-соединение https://ask.sqlservercentral.com/questions/17400/inner-join-vs-inner-hash-join.html