Comments 31
постепенно копировать строки пачками по n штук как-то так:
SELECT TOP n * FROM… WHERE copied = 0
и потом отмечать в скопированных строках copied = 1?
а третий способ разве не оно?Как я понял — там «маркером» того, что строки перенесены было их удаление из исходной таблицы после копирования. Удаление строки это намного более затратная операция по сравнению с изменением одного поля поля в строке. Учитывая, что сервер живой и там еще какие-то страсти с транзакциями-логированием удаленных строк — мне кажется мой вариант будет быстрее и не такой чувствительный для вебсервиса.
Она вроде как даже в лог не пишет, тоже плюс. Выгружать порциями, как в способе 3.
А еще можно попробовать настроить репликацию…
+1 за мастер экспорта импорта. Но он использует не bulk insert, а её другой аналог доступный только в .NET — прямая запись данных в таблицу, без всяких insert. Что-то вроде прямой передачи данных в бинарном формате. Однако, замечено на практике, что если ставить галочку на DELETE DATA BEFORE TRANSFER, и у вас осталось мало места а transaction log, то процесс все таки застревает. Возможно, для удаления он всё же используют transaction log.
Если есть кластерный индекс, любая запись должна пройти через движок БД, что бы попасть туда, куда ей нужно. А без кластерного индекса, потом будет реиндексация. Никакой «прямой записи» в принципе быть не может. Скорее всего, там оптимизация в момент записи. Просто монопольный захват таблиц или что-то в этом роде.
interfax.ru ©
И очень зря.
Та же SSMS использует под капотом именно его, а главное — это самый низкоуровневный и эффективный способ
Я как-то переносил достаточно большие таблицы. Таблички в несколько миллионов строк копируются за пару минут.
Ещё как писали в похожей статье по postgre, хороший способ:
1) переименовываем существующую таблицу в что-нибудь, например дописываем окончание _old
2) Создаём новую пустую таблицу с точно такой же структурой. Структуру взять не сложно, главное не забудьте про индексы. Сделать 1 и 2 запрос можно одним запросом, поэтому ни один скрипт не прервется, и просто запишет данные а новую таблицу. Простоя не будет.
3) имея неменяющуюся таблицу _old, можно начать её медленно переносить. Если планируете порционно, то вообще стоит удалить индексы (кроме главного ключевого ), потому-что удаляя после запроса по 100 000 записей, будут также перестраиваться все индексы, это дорогая операция для такой толстой таблицы. Ну а я все же рекомендую переносить через мастер экспорта импорта, он не будет перестраивать индексы пока все не перенесет .
using (var source = CreateSourceConnection())
using (var destination = CreateDestinationConnection())
{
// extract and transform, lazy
var sourceQuery = source.GetTable<SomeTable>()
.Select(s => new SomeDestTable{...});
// load data by 1000 records, configurable
destination.GetTable<SomeDestTable>().TableName("SomeNewName")
.BulkCopy(sourceQuery);
}
Данные влетают в базу со скоростью мысли, при чем это могут быть любые сервера и я одновременно могу делать Transform. Такой себе ETL через ORM.
Если же у вас базы на том же сервере. То почему же не сделать это одним запросом.
using (var source = CreateSourceConnection())
{
// extract and transform, lazy
var sourceQuery = source.GetTable<SomeTable>()
.Select(s => new SomeDestTable{...});
// appropriate INSERT INTO will be genarated
sourceQuery.Insert(source.GetTable<SomeDestTable>()
.DatabaseName("OtherDb").TableName("SomeNewName"));
}
Для чего давать советы по решению задачи, которые сам не пробовал?
Где-то слышал/читал/увидел, сам не попробовал, но расскажу, статью напишу побольше, тема важная.
Во-первых, вероятно вам может помочь удаление какого-либо столбца, однако это блокирующая операция, а не всегда есть возможность остановить web-сервис. И на Хабре есть статья, в которой рассказывается, как это можно осуществить.
Можно было бы сразу и ссылку прикрепить?
(5-2) Способа перенести большую SQL таблицу