Лучшая практика / производительность SQL при вставке в таблицу. Использовать временную таблицу или нет

#sql #sql-server

#sql #sql-server

Вопрос:

У меня есть запрос select, который возник из-за того, что я пытался удалить циклы while из существующего запроса, который был слишком медленным. В нынешнем виде я сначала выбираю во временную таблицу.

Затем из этой временной таблицы я вставляю в конечную таблицу значения из временной таблицы.

Ниже приведен упрощенный пример выполнения моего запроса

 select 
    b.BookId, 
    b.BookDescription, 
    a.Name,
    a.BirthDate, 
    a.CountryOfOrigin,
into #tempTable
from library.Book b
left join authors.Authors a
on a.AuthorId = b.AuthorId

insert into bookStore.BookStore
    ([BookStoreEntryId]
    [BookId],
    [BookDescription],
    [Author],
    [AuthorBirthdate],
    [AuthorCountryOfOrigin])
select 
    NEWID(),
    t.BookId,
    t.BookDescription,
    t.Name,
    t.Birthdate,
    t.CountryOfOrigin

from #tempTable t

drop table #tempTable
 

Было бы лучше переместить оператор select в начале ниже, чтобы он был включен в оператор insert, устраняя необходимость во временной таблице?

Комментарии:

1. Я не думаю, что вам нужна временная таблица здесь

2. @T.S. что бы вы назвали веской причиной для использования временной таблицы?

3. Как вы думаете, почему временная таблица повысит производительность, когда вы заставляете СУБД записывать данные в tempdb базу данных, а затем снова в базу данных. Во всяком случае, удаление DISTINCT будет гораздо более производительным.

4. Я предлагаю вам тщательно подумать о том, нужны ли вам DISTINCT и какие индексы у вас есть в таблице. Мне кажется, что временная таблица — это просто пластырь для решения более серьезных проблем

Ответ №1:

В этом случае нет никакого преимущества в наличии временной таблицы. Просто используйте запрос select напрямую.

Иногда временные таблицы могут повысить производительность. Один из методов заключается в том, что реальная таблица имеет реальную статистику (в частности, количество строк). Оптимизатор может использовать эту информацию для улучшения планов выполнения.

Временные таблицы также могут повысить производительность, если для них явно указан индекс.

Однако они несут накладные расходы на написание таблицы.

В этом случае вы просто получаете все накладные расходы, и пользы не должно быть.

На самом деле, я мог бы представить одно преимущество при одном обстоятельстве. Если выполнение запроса заняло много времени — скажем, потому, что соединение требовало объединения вложенных циклов без индексов, — тогда таблица назначения будет сохранена от блокировки и конфликтов, пока все строки не будут доступны для вставки. Однако это был бы необычный случай.

Комментарии:

1. Есть большая вероятность, что верхний выбор в реальном запросе может занять более часа. Исходный запрос до внесения изменений занимал примерно 6 часов из-за вложенных циклов while и относительно большого набора данных. В это время есть другие процессы, которые могут использовать целевую таблицу. Итак, если я не ошибаюсь, моя ситуация относится к вашему необычному случаю.

2. @DamianJacobs . , , Вполне возможно, «да». однако маловероятно, что какая-либо из ваших таблиц называется «книги» или «авторы».

3. Книги да, авторы нет. Фактический запрос связан с финансами и немного сложнее. Большое вам спасибо за ваши необычные обстоятельства. Я ценю мысль, которая привела к добавлению этого в ваш ответ.

Ответ №2:

Выполните за 1 шаг

 insert into bookStore.BookStore
    ( /* [BookStoreEntryId] <-- assuming this is auto id*/ 
    [BookId],
    [BookDescription],
    [Author],
    [AuthorBirthdate],
    [AuthorCountryOfOrigin])
SELECT distinct 
    b.BookId, 
    b.BookDescription, 
    a.Name,
    a.BirthDate, 
    a.CountryOfOrigin,
from library.Book b
left join authors.Authors a
on a.AuthorId = b.AuthorId
 

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