Я использую MS SQL, и мне нужно выполнить несколько запросов к одной и той же таблице по разным критериям. Сначала я выполнял каждый запрос в исходной таблице, хотя все они имеют некоторую фильтрацию (т. Е. Дата, статус). Это заняло много времени (около 2 минут).
В строках данных есть дубликаты, и все индексы НЕКЛАСТЕРИРОВАНЫ. Меня интересуют только 4 столбца для моих критериев, и результат должен выводить только количество для всех запросов.
колонны необходимо: TABLE
, FIELD
, AFTER
, DATE
, и есть индекс по каждому из DATE
и TABLE
.
После создания временной таблицы только с теми полями, которые мне нужны, она сократилась до 1:40 минут, что все еще очень плохо.
CREATE TABLE #TEMP
(
TABLE VARCHAR(30) NULL,
FIELD VARCHAR(30) NULL,
AFTER VARCHAR(1000) NULL,
DATE DATETIME,
SORT_ID INT IDENTITY(1,1)
)
CREATE CLUSTERED INDEX IX_ADT ON #TEMP(SORT_ID)
INSERT INTO #TEMP (TABLE, FIELD, AFTER, DATE)
SELECT TABLE, FIELD, AFTER, DATE
FROM mytbl WITH (NOLOCK)
WHERE TABLE = 'OTB' AND
FIELD = 'STATUS'
Runnig this -> (216598 строка (и) затронута)
Поскольку не все запросы зависят от диапазона дат, я не включил его в запрос. Проблема в том, что для вставки требуется более 1 минуты . Вышеуказанная вставка заняла 1:19 мин.
Я хочу запустить что-то вроде этого для нескольких запросов:
SELECT COUNT(*) AS COUNT
FROM #TEMP
WHERE AFTER = 'R' AND
DATE >= '2014-01-01' AND
DATE <= '2015-01-01'
Это проблема с вставкой больше, чем с выделением, но у temp гораздо меньше строк, чем в исходной таблице, что может быть лучше, чем проходить через таблицу несколько раз.
Как я могу оптимизировать это?
РЕДАКТИРОВАТЬ
Я удалил идентификатор сортировки, я думал, что проблема была в основном с выбором, а не вставкой. Это было предположение.
Я не могу создать уникальный для любого индекса, так как нет уникального поля или строк.
Я использую SQL Server 2012.
Таблица Info : Это куча и использует следующее пространство:
name rows reserved data index_size unused
mytbl 24869658 9204568 KB 3017952 KB 5816232 KB 370384 KB
SELECT COUNT(*) AS COUNT FROM original_table WHERE AFTER = 'R' AND DATE >= '2014-01-01' AND DATE < '2015-01-01'
, почему бы вам не попробовать оптимизировать каждый (запрос) по отдельности? Вам не разрешено добавлять индексы в таблицу?TABLE
иFIELD
столбцы из#temp
таблицы (все строки имеютTABLE = 'OTB' AND FIELD = 'STATUS'
для таблицы конкретного темпа после всех.)CREATE TABLE
утверждение). Падение было вызвано тем, что вопрос не был ясным.Ответы:
Вопрос в основном о том, как оптимизировать оператор select:
Удаление лишних проекций и добавление предполагаемой
dbo
схемы:Без индекса, как у
([TABLE],[FIELD]) INCLUDE ([AFTER],[DATE])
SQL Server, есть два основных варианта:[TABLE] = 'OTB'
и[FIELD] = 'STATUS'
( с помощьюIDX6
), а затем выполнить кучи (RID) поиск каждой строки для извлечения[AFTER]
и[DATE]
столбцов.Если оптимизатор выбирает кучу сканирование или индекс обратиться с РИД поиск зависит от предполагаемой селективности
[TABLE] = 'OTB'
и[FIELD] = 'STATUS'
предикатов. Проверьте, соответствует ли предполагаемое количество строк из поиска действительности. Если нет, обновите свою статистику. Протестируйте запрос с табличной подсказкой, заставляющей использовать индекс, если это условие является достаточно избирательным . Если в настоящее время оптимизатор выбирает поиск по индексу, протестируйте производительность с помощью подсказкиINDEX(0)
илиFORCESCAN
для сканирования кучи.Кроме того, можно немного улучшить сканирование кучи, удалив часть неиспользуемого пространства (370 МБ). В SQL Server 2008 это можно сделать, перестроив кучу. Неиспользуемое пространство в кучах часто является результатом удалений, выполненных без взятия блокировки таблицы (без блокировки таблицы пустые страницы не освобождаются из кучи). По этой причине таблицы с частым удалением часто лучше хранить в виде кластеризованной таблицы.
Производительность сканирования кучи зависит от того, сколько таблицы хранится в памяти, сколько нужно прочитать с диска, насколько заполнены страницы, скорость постоянного хранилища, независимо от того, связано ли сканирование с вводом-выводом или с ЦП ( параллелизм может помочь).
Если производительность по-прежнему неприемлема после того, как вы изучили все вышеперечисленное, попробуйте обосновать новый индекс. Если доступно в вашей версии SQL Server, возможный отфильтрованный индекс для данного запроса будет:
Также рассмотрите сжатие индекса, если это доступно и выгодно. Без какого-либо нового индекса вы сравнительно мало можете сделать для повышения производительности данного запроса.
источник
IDX6 nonclustered located on PRIMARY TABLE, FIELD
. Может быть, это изменит вещи, которые вы упомянули?Я думаю, что есть причина для изменения индексов здесь, потому что:
Это также было бы хорошим вариантом использования для некластеризованных индексов хранилища столбцов, представленных в SQL Server 2012, т.е. для суммирования / агрегирования нескольких столбцов в большой таблице со многими столбцами.
Хотя у этих индексов есть побочный эффект создания таблицы только для чтения (за исключением переключения разделов), они могут трансформировать производительность агрегированных запросов при соответствующих условиях. Аспект, доступный только для чтения, может управляться путем удаления и повторного создания индекса или простого переключения данных в таблицу.
Я настроил простую испытательную установку, чтобы имитировать ваши настройки, и увидел хорошее улучшение производительности:
Мои результаты, 6 секунд против 0,08 секунд:
Таким образом, попробуйте составить кейс с вашим боссом, чтобы изменить индексы, или, по крайней мере, создать какой-то ночной процесс, в котором эти записи будут вырезаны в таблицу / базу данных отчетов только для чтения, где вы сможете выполнять свою работу, и добавить индексирование. подходит для этой рабочей нагрузки.
источник