У меня есть семь больших таблиц, которые могут хранить от 100 до 1 миллиона строк в любое время. Я назову их LargeTable1
, LargeTable2
, LargeTable3
, LargeTable4
... LargeTable7
. Эти таблицы в основном статичны: нет обновлений и новых вставок. Они меняются только один раз каждые две недели или один раз в месяц, когда они усекаются, и каждая партия регистра вводится в каждую.Проблемы с производительностью с UNION больших таблиц
Все эти таблицы имеют три поля: Headquarter
, Country
и File
. Headquarter
и Country
- цифры в формате «000», хотя в двух из этих таблиц они обрабатываются как int
из-за некоторых других потребностей в системе.
У меня есть еще одна, гораздо меньшая таблица под названием Headquarters
с информацией о каждом головном офисе. В этой таблице очень мало записей. На самом деле не более 1000.
Теперь мне нужно создать хранимую процедуру, которая возвращает все те штаб-квартиры, которые отображаются в больших таблицах, но либо отсутствуют в таблице Headquarters
, либо были удалены (эта таблица удалена логически: у нее есть поле DeletionDate
для проверки это).
Это запрос, я попробовал: производительность
CREATE PROCEDURE deletedHeadquarters
AS
BEGIN
DECLARE @headquartersFiles TABLE
(
hq int,
countryFile varchar(MAX)
);
SET NOCOUNT ON
INSERT INTO @headquartersFiles
SELECT headquarter, CONCAT(country, ' (', file, ')')
FROM
(
SELECT DISTINCT CONVERT(int, headquarter) as headquarter,
CONVERT(int, country) as country,
file
FROM LargeTable1
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable2
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable3
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable4
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable5
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable6
UNION
SELECT DISTINCT headquarter,
country,
file
FROM LargeTable7
) TC
SELECT RIGHT('000' + CAST(st.headquarter AS VARCHAR(3)), 3) as headquarter,
MAX(s.deletionDate) as deletionDate,
STUFF
(
(SELECT DISTINCT ', ' + st2.countryFile
FROM @headquartersFiles st2
WHERE st2.headquarter = st.headquarter
FOR XML PATH('')),
1,
1,
''
) countryFile
FROM @headquartersFiles as st
LEFT JOIN headquarters s ON CONVERT(int, s.headquarter) = st.headquarter
WHERE s.headquarter IS NULL
OR s.deletionDate IS NOT NULL
GROUP BY st.headquarter
END
этого СП не достаточно хорошо для нашего приложения. В настоящее время она занимает около 50 секунд, чтобы закончить, со следующими общими строками для каждой таблицы (просто чтобы дать вам представление о размерах):
- LargeTable1: 1516666 строк
- LargeTable2: 645740 строк
- LargeTable3 : 1950121 ряды
- LargeTable4: 779336 ряды
- LargeTable5: 1100999 ряды
- LargeTable6: 16499 строк
- LargeTable7: 24454 строки
Что я могу сделать для повышения производительности? Я попытался сделать следующее, без особой разницы:
- Подставив в локальную таблицу партий, за исключение тех штаба я уже вставленным, а затем обновляет поле countryFile для тех, которые повторяются
- Создание представления для этого запроса UNION
- Создание индексов для LargeTables по головному поле
Я также подумал о том, чтобы вставить эту пропавшую штаб-квартиру в постоянную таблицу после изменения LargeTables
, но таблица Headquarters
может меняться чаще, и мне не нужно менять свой модуль, чтобы эти вещи были аккуратны и обновлены. Но если это наилучшая альтернатива, я бы пошел на это.
Благодаря
AFAIK предложение о союзе будет делать отчетливое, поэтому нет необходимости включать в себя выделение по выбору – vercelli
@vercelli В одной таблице может быть несколько строк с одной и той же комбинацией из штаб-квартиры страны. Удалит ли ЮНИОН их, даже если они придут из одного стола? – Heathcliff
@Heathcliff да, это то, что UNION делает. UNION ALL не будет. – Hogan