1

Мне нужно проанализировать данные (~ 60000 строк) из файла CSV и записать их в таблицу MSSQL (данные Date/Time and Value, которая является десятичным числом). Каждый день я получаю один такой файл CSV. Уловка заключается в том, что в CSV-файле, который я получаю каждый день, у меня есть данные за последние 5 дней, что означает, что у меня есть данные для дат, которые я уже писал в прошлые дни, но мне нужно заменить их данными из файл.Лучшая практика: Удалить и вставить против обновления

Я пытаюсь решить между двумя методами: Bulk удалением старых данных, что мне нужно переписать, когда я получаю новый файл CSV, и INSERT, против нахождения каждой записи на основе даты & времени и ID и обновить его ,

1.Что является лучшей практикой, которая приведет к меньшим фрагментарным и техническим проблемам в моей базе данных?

  1. Какой будет дешевле с точки зрения производительности?

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

EDIT: В случае, если я добавлю план обслуживания, который ежедневно восстанавливает индексы после того, как я делаю массовое удаление и вставку новых данных, этого будет достаточно, чтобы избежать проблем с фрагментацией, или есть что-то, что я отсутствует?

+3

Рассматривали ли вы 'MERGE '? –

+0

Являются ли предыдущие 4 дня данных такими же, какие у вас уже есть? Так что вы на самом деле ничего не обновили бы? –

+0

@ Да, спасибо, я никогда не слышал о «MERGE». Я изучил его сейчас, и мне кажется, может ли это сделать. Знаете ли вы последствия такого ежедневного «MERGE» в состоянии фрагментации базы данных? – LimS

ответ

1

Faster & Лучше всего удалить все старые данные, импортировать данные с помощью SSIS или массовой вставки в случае, если у вас нет SSIS, а затем перестроить фрагментированные индексы. В качестве примера можно привести script.

+0

Я не знаком с SSIS, но я видел, что он не поддерживается в SQL WEB EDITION 2008 R2, поэтому он не имеет для меня значения – LimS

+0

Вы можете использовать объемную вставку вместо SSIS, но она будет медленнее. –

0

Пойду с вставкой всех данных в CSV-файл и удаляю дубликаты данных.

Код, приведенный ниже, поможет вам удалить дубликаты. Я надеюсь, что это помогает :)

delete b from your_table c join 
(SELECT max(a.id) id, a.date 
FROM your_table a 

GROUP BY a.date 
having count(0) > 1 
) as b 
on c.date = b.date 
and c.id <> b.id 
+0

Спасибо @Liz, но что вы можете сказать мне о производительности и фрагментации? – LimS

+0

Если у вас есть тест с миллионами записей. И с соответствующими индексами он принимает пары секунд. О фрагментации могут дать вам любые мнения. Я не знаком с этим. –

0

Вот метод MERGE с использованием промежуточной таблицы с проанализированных данных CSV. В качестве альтернативы вы можете использовать параметр table value, а не источник промежуточной таблицы.

Что касается вашей фрагментации, она будет в основном зависеть от того, сколько новых строк будет вставлено в пределах существующего диапазона дат целевой таблицы. Без новых строк в этом диапазоне, фрагментация незначительна (менее 3% как сценарий ниже шоу. Вы можете всегда выполнять индекс REBUILD или REORGANIZE после ETL, если фрагментация становится проблематичным.

CREATE TABLE dbo.Test(
     TestDateTime datetime2(0) NOT NULL 
     CONSTRAINT PK_Test PRIMARY KEY 
    , TestData int NOT NULL 
    ); 
CREATE TABLE dbo.TestStaging(
     TestDateTime datetime2(0) NOT NULL 
     CONSTRAINT PK_TestStaging PRIMARY KEY 
    , TestData int NOT NULL 
    ); 
GO 

--load 10 days into main table (61710 per day) 
WITH 
    t4 AS (SELECT n FROM (VALUES(0),(0),(0),(0)) t(n)) 
    ,t256 AS (SELECT 0 AS n FROM t4 AS a CROSS JOIN t4 AS b CROSS JOIN t4 AS c CROSS JOIN t4 AS d) 
    ,t256K AS (SELECT ROW_NUMBER() OVER (ORDER BY (a.n)) - 1 AS num FROM t256 AS a CROSS JOIN t256 AS b CROSS JOIN t4 AS c) 
INSERT INTO dbo.Test WITH(TABLOCKX) (TestDateTime, TestData) 
SELECT DATEADD(second, num*7, CAST('2015-07-01T00:00:00' AS datetime2(0))), num 
FROM t256K 
WHERE num <= 123420; 
GO 

--load 4 most recent days with new values plus 1 new day into staging table 
WITH 
    t4 AS (SELECT n FROM (VALUES(0),(0),(0),(0)) t(n)) 
    ,t256 AS (SELECT 0 AS n FROM t4 AS a CROSS JOIN t4 AS b CROSS JOIN t4 AS c CROSS JOIN t4 AS d) 
    ,t256K AS (SELECT ROW_NUMBER() OVER (ORDER BY (a.n)) - 1 AS num FROM t256 AS a CROSS JOIN t256 AS b CROSS JOIN t4 AS c) 
INSERT INTO dbo.TestStaging WITH(TABLOCKX) (TestDateTime, TestData) 
SELECT DATEADD(second, num*7, CAST('2015-07-07T00:00:06' AS datetime2(0))), num 
FROM t256K 
WHERE num <= 61710; 
GO 

--show fragmentation before MERGE 
SELECT * 
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID(N'dbo.Test'), NULL, NULL, 'DETAILED'); 
GO 

MERGE dbo.Test AS target 
USING dbo.TestStaging AS source ON 
    source.TestDateTime = target.TestDateTime 
WHEN MATCHED THEN 
    UPDATE SET TestData = source.TestData 
WHEN NOT MATCHED BY target THEN 
    INSERT (TestDateTime, TestData) VALUES (source.TestDateTime, source.TestData); 
GO 

--show fragmentation after MERGE 
SELECT * 
FROM sys.dm_db_index_physical_stats(DB_ID(), OBJECT_ID(N'dbo.Test'), NULL, NULL, 'DETAILED'); 
GO