2015-06-09 3 views
0

мне нужно создать поддельные данные в fakeData таблице ниже этого psuedocode:BULK генерировать данные SQL Server

foreach(t1.id in table1) 
    foreach(t2.id in table2) 
     foreach(t3.id in table3) 
     INSERT INTO fakeData (t1.id, t2.id, t3.id, random(30,80)) 

Если идентификатор является первичным ключом этой таблицы.

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

Этот вопрос действительно состоит из двух частей: как я могу выполнить psuedocode в SQL Server, и что это лучший способ сделать это очень быстро. (У меня в настоящее время нет индексов)

Это может показаться дубликатом всего остального «Самый быстрый способ для массовой вставки». Я думаю, этот вопрос отличается тем, что данные я загрузки на самом деле может быть создан мой SQL Server, поэтому BULK генерируют по сравнению с BULK INSERT

PS: Я получил SQL Server 2012

Edit: Дополнительные данные

Это звездная схема. fakeData будет таблицей фактов.

table2 - это размер даты 20 лет, с 7300 записями. table3 - это размер времени 96 записей. table1 - еще одно измерение с 100 миллионами записей.

+0

Есть ли одинаковое количество идентификаторов в таблицах 1, 2 и 3? Связаны ли идентификаторы? Некоторые примеры данных были бы полезны. –

+0

- все ли идентификаторы являются иностранными ключами для 'fakeData'? – ParoX

+0

Да, идентификаторы являются внешними ключами для fakeData. После вставки я сделаю PK-композицию из всех 3 идентификаторов. – LearningJrDev

ответ

0

Вы можете вставить данные очень быстро, используя BCP. Если столбец PK является столбцом идентификации, он все равно будет работать. Если нет, вы можете пропустить часть BCP и просто вставить с петлями while.

Чтобы создать файл BCP:

  1. в цикле, заполнить таблицу быстро с фиксированным # строк (скажем, 1 миллион).
  2. BCP вывести данные в файл BCP.
  3. BCP данные обратно в столько раз, сколько вы хотите

Сделайте это для каждой таблицы необходимо (псевдо код ниже):

Пример: - если это DEV машина, то я бы изменить модель восстановления на простой, - если это еще не сделано, чтобы уменьшить количество ведения журнала. затем изменить его обратно - к тому, что это было ранее

BEGIN TRAN 

declare @x int = 1 
while @x <= 1000000 
begin 
    insert into t1 (col1, col2) values (rand() * 100, rand(123) * 100) 

    if (@x % 10000) = 0 
    begin 
     COMMIT TRAN 
     BEGIN TRAN 
    end 

    set @x = @x + 1 
end 

COMMIT TRAN 

Затем bcp из данных (из командной строки), чтобы создать файл BCP

bcp out [dbname].dbo.t1 c:\file1.bcp -T 

Теперь BCP в (от командной строки) данных столько раз, сколько необходимо

bcp in [dbname].dbo.t1 c:\file1.bcp -T 
bcp in [dbname].dbo.t1 c:\file1.bcp -T 
bcp in [dbname].dbo.t1 c:\file1.bcp -T 
bcp in [dbname].dbo.t1 c:\file1.bcp -T 
bcp in [dbname].dbo.t1 c:\file1.bcp -T 
+0

Проблема в том, что col1, col2, col3 будут иметь на них первичный ключ. Похоже, что это копирование данных приведет к аннулированию уникального свойства, необходимого для ПК. – LearningJrDev

+0

Вы правы, я пропустил это. Однако, если столбец PK идентичен, тогда есть простые способы обхода проблемы, я считаю, что bcp as is будет работать, поскольку -E не включен. Если нет, то вы можете легко исключить часть bcp. Вставка цикла оптимизируется, когда протоколирование минимизируется, а коммиты сводятся к минимуму, оба из которых адресуются в репродуцирование. – Greg

+0

См. Решение, которое я разместил, воспользовавшись этим. Потребуется 69 дней с текущей скоростью. – LearningJrDev

0

Первая часть достаточно проста;

Insert Into FakeData 
Select T1.id as T1ID, T2.id as T2ID, T3.id as T3ID 
From Table1 T1, Table2 T2, Table3 T3 

Это будет декартово объединение трех таблиц и вернуть все возможные комбинации.Однако, если вы говорите о миллиардах возможных комбинаций, пакетная обработка, вероятно, хорошая идея. Я буду использовать смещение, потому что это легко понять, но вы, вероятно, можете найти более эффективный способ, я также собираюсь хранить результаты в таблице temp, поэтому вы запускаете только одно соединение, а остальные - выбор и вставки.

Declare @BatchSize int = 100000 
Declare @RowsToBeInserted bigint = 
((select count(1) as t1count from Table1) * 
(select count(1) as t2count from Table2) * 
(select count(1) as t3count from Table3)) 
Declare @Iterations int = 0 
Declare @CompletedRowCount bigint = 0 

Select T1.id as T1ID, T2.id as T2ID, T3.id as T3ID 
Into #TempTable 
From Table1 T1, Table2 T2, Table3 T3 

While @CompletedRowCount < @RowsToBeInserted 
begin 

Insert into FakeData 
select T1ID, T2ID, T3ID 
Order by T1ID, T2ID, T3ID 
Offset @CompletedRowCount 
Fetch next @BatchSize Only 
set @Iterations = @Iterations + 1 
set @CompletedRowCount = @Iterations * @BatchSize 

end 

Это должно позволить вам набирать размер партии в соответствии с тем, что лучше всего подходит для вашего сервера. При отсутствии индексов вам не нужно их бросать и воссоздавать для повышения производительности. Надеюсь, это указывает на правильное направление.

+0

Множество ошибок, которые я должен был исправить, например, не было ключевого слова rows после смещения и выборки. Также я не вижу смысла в этом, если SELECT INTO в таблице temp делает именно то, что мне нужно, потому что это делается партиями? Просто положить миллиарды записей в временную таблицу - это пустая трата пространства, не уверенный, что я очень хорошо понимаю этот метод - – LearningJrDev

+0

Если он будет терпеть неудачу при вставке, по крайней мере, он не будет вставляться в таблицу temp, поэтому никакого вреда не будет. Temp DB должен находиться на другом физическом разделе из данных, что означает, что чтение и запись могут выполняться одновременно. Также вам придется упорствовать в результате декартового соединения, потому что вы не хотите запускать его для каждой партии. Я полагаю, вы могли бы свалить его в файл, но с 70 080 000 000 000 записей sql, вероятно, не будет хорошо работать с любым созданным вами файлом. Конечно, я не думаю, что sql будет хорошо играть с 70 триллионами записей за один стол. – Randall

0

Хорошо, хорошо ... Так как никто действительно не показывал, как делать случайные значения. Я до сих пор вносил свой вклад в решение. Я делаю это прямо сейчас, наряду с моделью восстановления простой:

BEGIN TRAN 

declare @x int = 1 
while @x <= 5000 
begin 
INSERT INTO dimSpeed 
Select T1.id as T1ID, T2.DateValue as T2ID, T3.TIME_ID as T3ID, ABS(Checksum(NewID()) % 70) + 20 
From lines T1, dimDate T2, dimTime T3 
WHERE T1.id = @x AND T2.DateValue > '1/1/2015' AND T2.DateValue < '1/1/2016' 

    if (@x % 100) = 0 
    begin 
     COMMIT TRAN 
     BEGIN TRAN 
    end 

    set @x = @x + 1 
end 

COMMIT TRAN 

Где 5000 как многие элементы TABLE1 (t1) Я вставив. Выполнение всего 5000 занимает 5 минут или около того. При такой ставке потребуется 70 дней, чтобы вставить все необходимые данные. Требуется скорейший вариант

+0

Я делаю 170 миллионов INSERTS в течение 9 минут, что составляет около 5 МБ в секунду ... Столько возможностей для улучшения, а не увеличения моего жесткого диска – LearningJrDev