Объяснение запроса:
Person
(обозначаетсяPersonID
) может иметь или не иметь соответствующийJob
(обозначаетсяJobID
).- Если есть соответствующий
Job
, привязка сохраняется в таблицеPersonJob
(PersonID
‹=>JobID
). Person
безJob
игнорируются.Job
также имеетCityID
.- Для каждого
Job.CityID
запрос хочет знать общее количествоPerson
, а также количество уникальныхPerson.HouseID
Запрос:
SELECT
Job.CityID, COUNT(1) NumTotal, COUNT(DISTINCT(Person.HouseID)) NumDistinct
FROM
Job
INNER JOIN PersonJob ON (PersonJob.JobID = Job.JobID)
INNER JOIN Person ON (Person.PersonID = PersonJob.PersonID)
GROUP BY
Job.CityID
Статистика:
SELECT COUNT(1) FROM PersonJob
~ 600.000SELECT COUNT(1) FROM Person
~ 800.000SELECT COUNT(DISTINCT(Person.HouseID)) FROM Person
~ 10.000SELECT COUNT(1) FROM Job
~ 500- MS SQL Server 10.50
Проблема:
COUNT(1)
часть запроса при отдельном запуске выполняется за 0,25 с.SELECT Job.CityID, COUNT(1) NumTotal FROM Job INNER JOIN PersonJob ON (PersonJob.JobID = Job.JobID) INNER JOIN Person ON (Person.PersonID = PersonJob.PersonID) GROUP BY Job.CityID
COUNT(DISTINCT(Person.HouseID))
часть запроса при отдельном запуске выполняется за 0,80 сек.SELECT Job.CityID, COUNT(DISTINCT(Person.HouseID)) NumDistinct FROM Job INNER JOIN PersonJob ON (PersonJob.JobID = Job.JobID) INNER JOIN Person ON (Person.PersonID = PersonJob.PersonID) GROUP BY Job.CityID
Весь запрос выполняется за 3,10 сек — в 3 раза медленнее, почему?
Планы выполнения:
- Я не специалист в их чтении, извините.
- Насколько я могу судить, проблема заключается в COUNT(DISTINCT)
- In partial query:
- 25% Hash match (Aggregate) (output
Job.CityID
) - 15% Hash match (Inner Join) (output
Job.CityID
,Person.HouseID
)- 30% Index scan (output
Person.PersonID
,Person.HouseID
) - 14% поиск по индексу (выход
PersonJob.PersonID
)
- 30% Index scan (output
- 25% Hash match (Aggregate) (output
- In full query:
- 03% Hash match (Partial aggregate) (output
Job.CityID
,COUNT(*)
) - Совпадение хэша 31% (совокупность) (выход
Job.CityID
) - 29% Таблица Spool (выход
Job.CityID
,Person.HouseID
)
- 03% Hash match (Partial aggregate) (output
join
? - person Gordon Linoff   schedule 19.10.2016distinct
НЕ является функцией.distinct (Person.HouseID)
точно то же самое, что иdistinct Person.HouseID
- person a_horse_with_no_name   schedule 19.10.2016