Редактировать: +1 работает в этой ситуации, потому что оказывается, что FILE_NUMBER
это строковая версия целого числа с нулевым дополнением. Лучшим решением здесь для строк является добавление ''
(пустая строка), так как добавление значения может повлиять на порядок, или для чисел добавление чего-то, что является константой, но содержит недетерминированную функцию, например sign(rand()+1)
. Идея «сломать сортировку» все еще актуальна, просто мой метод не был идеальным.
+1
Нет, я не имею в виду, что я согласен ни с чем, я имею в виду это как решение. Если вы измените свой запрос на, ORDER BY cj.FILE_NUMBER + 1
то он TOP 1
будет вести себя по-другому.
Видите ли, с целью небольшого ряда для упорядоченного запроса, система будет пытаться использовать данные по порядку, чтобы избежать использования оператора сортировки. Это также позволит избежать построения хеш-таблицы, полагая, что, вероятно, не нужно делать слишком много работы, чтобы найти эту первую строку. В вашем случае это неверно - из-за толщины этих стрелок кажется, что для поиска одного совпадения приходится использовать много данных.
Толщина этих стрелок говорит о том, что ваша DOCUMENT_QUEUE
таблица (DQ) намного меньше вашей CORRESPONDENCE_JOURNAL
таблицы (CJ). И что лучший план на самом деле будет проверять через строки DQ, пока не будет найдена строка CJ. В самом деле, именно это и сделал бы Query Optimizer (QO), если бы в нем не было этого противного ORDER BY
, что хорошо поддерживается индексом покрытия на CJ.
Поэтому, если вы отбросите ORDER BY
полностью, я ожидаю, что вы получите план, который включает в себя вложенный цикл, перебирая строки в DQ, пытаясь найти CJ, чтобы убедиться, что строка существует. И с TOP 1
этим это прекратилось бы после того, как был потянут один ряд.
Но если вам действительно нужна первая строка по FILE_NUMBER
порядку, то вы могли бы заставить систему игнорировать этот индекс, который (неправильно) кажется очень полезным, выполняя ORDER BY CJ.FILE_NUMBER+1
- что, как мы знаем, будет поддерживать тот же порядок, что и раньше, но, что важно, QO не делает. QO будет сосредоточен на получении полного набора, так что оператор Top N Sort может быть удовлетворен. Этот метод должен создать план, который содержит оператор Compute Scalar для определения значения порядка и оператор Top N Sort для получения первой строки. Но справа от них вы должны увидеть хороший Nested Loop, выполняющий множество поисков на CJ. И лучшая производительность, чем пробежка по большой таблице строк, которые ничего не соответствуют в DQ.
Hash Match не обязательно ужасен, но если набор строк, которые вы возвращаете из DQ, намного меньше, чем CJ (как я и ожидал), то Hash Match будет сканировать намного больше CJ чем это нужно.
Примечание: я использовал +1 вместо +0, потому что оптимизатор запросов может распознать, что +0 ничего не меняет. Конечно, то же самое может относиться к +1, если не сейчас, то в какой-то момент в будущем.
DOCUMENT_ID
связь между двумя таблицами (или у каждой записиCORRESPONDENCE_JOURNAL
есть соответствующая записьDOCUMENT_QUEUE
)?