Я объединяю небольшую таблицу (1000 строк) с большой таблицей (8 миллионов строк) в SQL Server 2008. Объединение использует некластеризованный покрывающий индекс для большой таблицы, и объединение может создать три возможных плана запросов. Я пытаюсь выяснить, какой план лучше, но я также хочу обобщить эти знания, чтобы в следующий раз я мог лучше знать, какую эвристику использовать при просмотре статистики ввода-вывода SQL.
План № 1 является циклическим соединением и генерирует статистику для большой таблицы следующим образом:
Scan count 2582, logical reads 35686, physical reads 1041, read-ahead reads 23052
План № 2 является объединением слиянием и генерирует такую статистику:
Scan count 1, logical reads 59034, physical reads 49, read-ahead reads 59004
План № 3 является хеш-соединением и генерирует такую статистику:
Scan count 3, logical reads 59011, physical reads 5, read-ahead reads 59010
Индекс покрытия упорядочен по (ID, Date)
. Запрос возвращает данные для примерно 50% идентификаторов и для каждого идентификатора возвращает непрерывный фрагмент данных за последние 3 месяца, который обычно составляет около 1/4 или строки для каждого идентификатора. Запрос возвращает около 1/8 от общего числа строк в индексе. Другими словами, запрос является редким, но последовательным.
Я предполагаю, что план № 1 ужасен для этой рабочей нагрузки, потому что перемещение головки диска в 2500 раз (или даже в 1041 раз) намного дороже, чем последовательное сканирование диска. Я также предполагаю, что # 3 и # 2 имеют схожие, последовательные (и, следовательно, более эффективные) шаблоны ввода / вывода.
Но есть ли случай, когда план № 1 действительно лучший, где «лучший» означает меньшее влияние на подсистему ввода-вывода и меньшее влияние на другие запросы, выполняемые одновременно?
Или это действительно зависит от многих переменных, таких как тип дисковой подсистемы, фрагментация индекса и т. Д. Если «это зависит», есть ли какие-то практические правила для решения проблемы?