Как заставить представление союзов работать более эффективно?

8

У меня есть большая таблица (от десятков до сотен миллионов записей), которую мы разбили по соображениям производительности на активные и архивные таблицы, используя прямое сопоставление полей и выполняя процесс архивирования каждую ночь.

В некоторых местах нашего кода нам нужно запускать запросы, которые объединяют активные и архивные таблицы, почти неизменно фильтруемые одним или несколькими полями (которые мы явно поместили в обе таблицы). Для удобства было бы целесообразно иметь такой вид:

create view vMyTable_Combined as
select * from MyTable_Active
union all
select * from MyTable_Archive

Но если я запускаю запрос, как

select * from vMyTable_Combined where IndexedField = @val

он объединит все, от Active и Store до фильтрации @val, что снизит производительность.

Есть ли какой-нибудь умный способ заставить два подзапроса объединения просматривать каждый фильтр @valдо того, как они создадут объединение?

Или, может быть, есть какой-то другой подход, который вы бы предложили, чтобы достичь того, чего я добиваюсь, то есть простой и эффективный способ получения набора записей объединения, отфильтрованного по индексированному полю?

РЕДАКТИРОВАТЬ: вот план выполнения (и вы увидите реальные имена таблиц здесь):

план выполнения

Как ни странно, активная таблица на самом деле использует правильный индекс (плюс поиск RID?), Но архивная таблица выполняет сканирование таблицы!

Шауль Бер
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Пол Уайт 9

Ответы:

8

Комментарии к вопросу показывают, что проблема заключается в том, что тестовая база данных, которую ОП использовал для разработки запроса, имела радикально отличающиеся характеристики данных, чем производственная база данных. В нем было намного меньше строк, а поле, используемое для фильтрации, было недостаточно избирательным.

Когда число различных значений в столбце слишком мало, индекс может быть недостаточно избирательным. В этом случае последовательное сканирование таблицы обходится дешевле, чем поиск индекса / поиск строки. Обычно при сканировании таблиц используется последовательный ввод-вывод, который намного быстрее чтения с произвольным доступом.

Часто, если запрос вернет больше, чем несколько процентов строк, дешевле будет просто выполнить сканирование таблицы, чем поиск по индексу / поиск по строке или подобную операцию, которая интенсивно использует случайный ввод-вывод.

ConcernedOfTunbridgeWells
источник
1

Просто чтобы добавить, что я нашел. Если вы делаете:

create view vMyTable_Combined as
select *, 1 AS [Active] from MyTable_Active
union all
select *, 0 AS [Active] from MyTable_Archive

Затем вы можете отфильтровать поле [Active] и убедиться, что другая часть не загружена.

Майкл Молдруп
источник