Гость
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Два подхода к обновлению данных / 5 сообщений из 5, страница 1 из 1
03.03.2020, 10:38
    #39933350
a_voronin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Два подхода к обновлению данных
Господа, часто возникает необходимость обновлять в таблице некий диапазон данных. Простейшее решение, к которому многие прибегают -- это "все удалить -- все вставить".

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
CREATE TABLE X(ID INT IDENTITY(1,1), DT DATETIME, VAL NVARCHAR(10), AMOUNT DECIMAL(18,4))

INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-01', N'Коровы', 10.5)
INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-02', N'Куры', 150.2)
INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-03', N'Свиньи', 70.1)
INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-04', N'Голуби', 7)

DELETE FROM X WHERE DT >= '2020-01-02'

INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-02', N'Куры', 150.2)
INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-03', N'Свиньи', 76.1)
INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-03', N'Овцы', 66.7)

SELECT * FROM X
GO 
DROP TABLE X
GO 



Но существует другой подход -- провести подробное сравнение и обновить только то, что нужно.

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
CREATE TABLE X(ID INT IDENTITY(1,1), DT DATETIME, VAL NVARCHAR(10), AMOUNT DECIMAL(18,4))
GO
INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-01', N'Коровы', 10.5)
INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-02', N'Куры', 150.2)
INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-03', N'Свиньи', 70.1)
INSERT INTO X(DT, VAL, AMOUNT) VALUES('2020-01-04', N'Голуби', 7)

MERGE X AS Target
USING (
	SELECT * FROM (
		VALUES(	'2020-01-02', N'Куры', 150.2),
				('2020-01-03', N'Свиньи', 76.1),
				('2020-01-03', N'Овцы', 66.7)
	) Source(DT, VAL, AMOUNT) 
) AS Source ON Source.DT = Target.DT AND Source.VAL = Target.VAL
WHEN MATCHED AND Target.DT >= '2020-01-02' AND Target.AMOUNT <> Source.AMOUNT THEN 
    UPDATE SET Target.AMOUNT = Source.AMOUNT
WHEN NOT MATCHED BY SOURCE AND Target.DT >= '2020-01-02' THEN 
    DELETE 
WHEN NOT MATCHED BY TARGET THEN 
    INSERT (DT, VAL, AMOUNT) VALUES(DT, VAL, AMOUNT)
;

SELECT * FROM X

GO 
DROP TABLE X



Второй подход естественно требует более громоздкого кода.

Вопрос: при каких обстоятельствах с точки зрения производительности стоит прибегать к первому, а в каких ко второму подходу? И как определить грань, где какой будет оптимален?
...
Рейтинг: 0 / 0
03.03.2020, 10:41
    #39933354
L_argo
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Два подхода к обновлению данных
При больших объемах, но небольших приращениях "вставить все" это очень неоптимально.
Грань определяется только импирически.
...
Рейтинг: 0 / 0
03.03.2020, 11:51
    #39933410
Владислав Колосов
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Два подхода к обновлению данных
a_voronin,

если вам нужна высокая доступность, то делайте через переключение секций. Таблицу на замещение секции можно заполнить вставкой, если это быстрее.
...
Рейтинг: 0 / 0
03.03.2020, 11:53
    #39933416
a_voronin
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Два подхода к обновлению данных
Владислав Колосов,

Речь идет о тонком обновлении, которое может включать применительно к конкретным записям INSERT UPDATE DELETE NOCHANGE. Соответственно никакое переключение секций тут не поможет. Разве что делать обновление в соседней таблице и потом перегонят и инкремент.
...
Рейтинг: 0 / 0
03.03.2020, 14:50
    #39933559
Ferdipux
Гость
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Два подхода к обновлению данных
a_voronin,

IMHO, Если таблица Х - обычная, то при наличии необходимых индексов (см. Optimizing MERGE Statement Performance ) и прочих условий MERGE может быть быстрее. А может и не быть - в вашем "простом" примере удаление идет с фильтром по DT, если по нему есть индекс - DELETE + INSERT может быть быстрее, не требуется сличать записи по ключу DT+VAL.

Если таблица типа columnstore, то DELETE + INSERT однозначно выигрывает у MERGE.
...
Рейтинг: 0 / 0
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Два подхода к обновлению данных / 5 сообщений из 5, страница 1 из 1
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]