Как я могу ускорить этот простой запрос? - PullRequest
1 голос
/ 16 ноября 2011

Представьте, что у вас есть эти 3 таблицы:

enter image description here

И представьте, что в соответствии с этой схемой есть огромные данные.

Когда я запускаю запрос, подобный этому:

SELECT DISTINCT tPerson.Name, tPerson.Town
FROM tPerson
JOIN tPersonTypeCodeMap ON tPersonTypeCodeMap.PersonId = tPerson.Id
JOIN tPersonHobbyCodeMap ON tPersonHobbyCodeMap.PersonId = tPerson.Id
WHERE tPersonTypeCodeMap.TypeCode IN ('C', 'S', 'P')

Работает довольно быстро!

Но когда я добавляю второе условие (НЕ В), запрос принимает возраст:

SELECT DISTINCT tPerson.Name, tPerson.Town
FROM tPerson
JOIN tPersonTypeCodeMap ON tPersonTypeCodeMap.PersonId = tPerson.Id
JOIN tPersonHobbyCodeMap ON tPersonHobbyCodeMap.PersonId = tPerson.Id
WHERE tPersonTypeCodeMap.TypeCode IN ('C', 'S', 'P')
 OR tPersonHobbCodeMap.HobbyCode NOT IN ('SKATE','CLIMBING') 

Можете ли выСкажите, в чем причина замедления запроса и как я могу заставить его работать быстрее?

Ответы [ 2 ]

2 голосов
/ 16 ноября 2011

В первом запросе большую часть фильтрации можно выполнить, просматривая только одну таблицу (tpersonTypeCodeMap).Во втором примере необходимо объединить две таблицы для выполнения фильтрации.Кроме того, когда вы вводите «ИЛИ», вы теряете эффект любого индекса.

Действительно ли верно, что вы хотите, чтобы «ИЛИ» работало с этими двумя фильтрами, а не «И»?Кроме того, верно ли, что вы хотите, чтобы возвращалось несколько записей на человека, в зависимости от того, сколько типов кодов они соответствуют и сколько кодов Hobby они не соответствуют ?

Если условие "ИЛИ" имеет значение,фактически, то, что вы хотите, вы можете использовать:

SELECT tPerson.Name, tPerson.Town
FROM tPerson JOIN tPersonTypeCodeMap 
     ON tPersonTypeCodeMap.PersonId = tPerson.Id
WHERE tPersonTypeCodeMap.TypeCode IN ('C', 'S', 'P')
UNION
SELECT tPerson.Name, tPerson.Town JOIN tPersonHobbyCodeMap 
       ON tPersonHobbyCodeMap.PersonId = tPerson.Id
WHERE tPersonHobbCodeMap.HobbyCode NOT IN ('SKATE','CLIMBING')

Это позволит получить два набора записей независимо, а затем объединить их вместе.При использовании UNION вместо UNION ALL будет возвращена операция DISTINCT, чтобы преобразовать базу данных в уникальные строки.

0 голосов
/ 16 ноября 2011

Часть NOT IN не будет работать хорошо. Попробуйте эту версию.

SELECT tPerson.Name, tPerson.Town
FROM tPerson
JOIN tPersonTypeCodeMap ON tPersonTypeCodeMap.PersonId = tPerson.Id
WHERE tPersonTypeCodeMap.TypeCode IN ('C', 'S', 'P')
 OR NOT EXISTS(SELECT NULL
                   FROM tPersonHobbCodeMap 
                   WHERE tPersonHobbCodeMap.PersonId = tPerson.id
                       AND tPersonHobbCodeMap.HobbyCode IN ('SKATE','CLIMBING') )
...