powered by simpleCommunicator - 2.0.60     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Удаление дубликатов - страшно долго
18 сообщений из 43, страница 2 из 2
Удаление дубликатов - страшно долго
    #39708004
PizzaPizza
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pavell450Выполняется 6-10 часов...

Таблица MATERIAL содержит 75 933 записей
Выборка SELECT min(MATERIALID) as ID FROM MATERIAL GROUP BY RATE, TITLE , RESCODE
дает 43 228 записей.

Вопрос знатокам:
Корректен ли такой запрос для удаления дубликатов?
за 10 часов удалено 3600 записей...
Может быть надо что-то настроить на сервере, в структуре БД? Индекс создать...
Или нужно переписать запрос полностью, революционно?
Заранее признателен всем, кто откликнется.

Это все не нормально совсем. При том, что сам запрос неэффективный, удаление не должно занимать часы.
Если у вас нет полного доступа к серверу - трогать ничего не рекомендую.
зы. Триггер ваш тоже жуткий.

Без плана запроса нельзя сказать что у вас за проблема. Вставьте SET SHOWPLAN_XML ON; + запрос в SSMS , запросите актуальный план, запустите запрос и прервите если не выполнится сразу. Правой кнопочкой по картинке плана и выбираете XML и постите сюда.

зы. только что понял, что никогда не сталкивался с долгими запросами и не знаю, покажет ли SSMS актуальный план для не выполненного запроса.
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708007
PizzaPizza
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SELECT [...] FROM MATERIAL WHERE MATERIALID NOT IN ( SELECT min(MATERIALID) as ID FROM MATERIAL GROUP BY RATE, TITLE , RESCODE )
тоже у вас часы выполняется?
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708011
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
PizzaPizzapavell450Выполняется 6-10 часов...

Таблица MATERIAL содержит 75 933 записей
Выборка SELECT min(MATERIALID) as ID FROM MATERIAL GROUP BY RATE, TITLE , RESCODE
дает 43 228 записей.

Вопрос знатокам:
Корректен ли такой запрос для удаления дубликатов?
за 10 часов удалено 3600 записей...
Может быть надо что-то настроить на сервере, в структуре БД? Индекс создать...
Или нужно переписать запрос полностью, революционно?
Заранее признателен всем, кто откликнется.

Это все не нормально совсем. При том, что сам запрос неэффективный, удаление не должно занимать часы.
Если у вас нет полного доступа к серверу - трогать ничего не рекомендую.
зы. Триггер ваш тоже жуткий.

Без плана запроса нельзя сказать что у вас за проблема. Вставьте SET SHOWPLAN_XML ON; + запрос в SSMS , запросите актуальный план, запустите запрос и прервите если не выполнится сразу. Правой кнопочкой по картинке плана и выбираете XML и постите сюда.

зы. только что понял, что никогда не сталкивался с долгими запросами и не знаю, покажет ли SSMS актуальный план для не выполненного запроса.
вот бывает же так, пришёл человек и по полочкам всё разложил, золото.
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708018
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
aleks222Откровение Иоанна-программизда?
Сортировать и нумеровать ВСЕ записи внезапно стало быстрее?
О темпора, о морес!Дарагуля, видимо ты за своим любимым делом (надувание щек) последние знания растерял.
Может стоило подумать сколько раз твой опус будет полностью сканировать таблицу (индекс)? И чем поможет предложенный индекс?

aleks222
Код: sql
1.
2.
3.
delete t
from MATERIAL as t
WHERE not exists( select * from MATERIAL as t1 where t1.MATERIALID < t.MATERIALID and t1.RATE = t.RATE and t1.TITLE  = t.TITLE  and t1.RESCODE = t.RESCODE )

Не пробовал подумать, что этот запрос поудаляет?

Изучай, может это сподвигнет тебя на освоение матчасти (хотя я очень сильно сомневаюсь):
Код: 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.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
58.
59.
60.
61.
62.
63.
64.
65.
66.
67.
68.
69.
70.
71.
72.
73.
74.
75.
76.
77.
78.
79.
80.
81.
82.
83.
84.
85.
use tempdb;
go

create table dbo.t (id int identity primary key, f1 numeric(18,2), f2 varchar(100), f3 int);

insert into dbo.t
 (f1, f2, f3)
select
 f1, f2, f3
from
 (
  select top (20000)
   rand(checksum(newid())) * 1000, cast(newid() as varchar(100)), rand(checksum(newid())) * 10000
  from
   master.dbo.spt_values a cross join
   master.dbo.spt_values b
 ) t1(f1, f2, f3) cross apply
 (select top (cast(rand(checksum(t1.f1, t1.f2, t1.f3)) * 100 + 1 as int)) Number from master.dbo.spt_values) t2;
go

declare @rows int, @ms int, @dt datetime2, @show_stat bit = 0, @create_index bit = 0, @show_result bit = 0;

declare @result table (description varchar(100), elapsed_time int, rows_deleted int);

/*Индекс, настоятельно рекомендованный aleks222*/
if @create_index = 1
 create index IX_t on dbo.t (f1, f2, f3, id);

/*Супер быстрый запрос от aleks222*/
set @dt = sysdatetime();
begin tran;

if @show_stat = 1 set statistics xml, io on;
delete a
from
 dbo.t a
where
 exists(select 1 from dbo.t b where b.f1 = a.f1 and b.f2 = a.f2 and b.f3 = a.f3 and b.id < a.id)
option
 (maxdop 1);
select @rows = @@rowcount, @ms = datediff(ms, @dt, sysdatetime());
if @show_stat = 1 set statistics xml, io off;

insert into @result values ('Супер быстрый запрос от aleks222', @ms, @rows);
if @show_result = 1 select * from dbo.t order by id;
rollback;

/*Супер медленный запрос от invm*/
set @dt = sysdatetime();
begin tran;

if @show_stat = 1 set statistics xml, io on;
with t as
(
 select row_number() over (partition by f1, f2, f3 order by id) as rn from dbo.t
)
delete t where rn > 1
option
 (maxdop 1);
select @rows = @@rowcount, @ms = datediff(ms, @dt, sysdatetime());
if @show_stat = 1 set statistics xml, io off;

insert into @result values ('Супер медленный запрос от invm', @ms, @rows);
if @show_result = 1 select * from dbo.t order by id;
rollback;

/*Исходный вариант*/
set @dt = sysdatetime();
begin tran;

if @show_stat = 1 set statistics xml, io on;
delete from dbo.t where id not in (select min(id) from dbo.t group by f1, f2, f3) option (maxdop 1);
select @rows = @@rowcount, @ms = datediff(ms, @dt, sysdatetime());
if @show_stat = 1 set statistics xml, io off;

insert into @result values ('Исходный вариант', @ms, @rows);
if @show_result = 1 select * from dbo.t order by id;
rollback;

/*Та-дам!*/
select * from @result order by elapsed_time;
go

drop table dbo.t;
go


Результат без индексаdescriptionelapsed_timerows_deletedСупер медленный запрос от invm3433984746Супер быстрый запрос от aleks2223754984746Исходный вариант5191984746

Результат с индексомdescriptionelapsed_timerows_deletedСупер медленный запрос от invm6391991233Супер быстрый запрос от aleks2226980991233Исходный вариант8976991233
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708066
Гавриленко Сергей Алексеевич
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Модератор: invm и aleks222, хорош какашками кидаться друг в друга; как дети малые, ей богу.
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708761
pavell450
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm,
Спасибо!
А вот и план запроса
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708766
pavell450
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
invm,
Спасибо!
А вот и план запроса
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708809
PizzaPizza
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pavell450,

"Ну у вас и запросы" - сказала база и повисла

А что такое Table="[ASSEMBLY_MATERIAL]" и какое отношение эта таблица имеет к вашему запросу?
Или же ваша таблица "MATERIAL" вовсе не таблица, а вьюшка и вы из неё удаляете?
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708821
PizzaPizza
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pavell450,

Declare @Title nvarchar(max)

@Title = Title

WHERE l.TITLE like @Title"

CONVERT_IMPLICIT(nvarchar(4000),[@Title],0)"

GROUP BY RATE, TITLE


ИМХО группировки и сравнения по nvarchar(4000) или nvarchar(max) = тормоза
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708838
Glebanski
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pavell450,

Выберите одного кандидата на удаление указав конкретные значения RATE, TITLE , RESCODE.
и добавьте в условие вашего запроса через AND.
Запустите Profiler и посмотрите, что там ваш запрос вытворяет.
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708841
invm
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pavell450А вот и план запросаЖуть кошмарная...
Вы там вместо обработки только строк с "дубликатами" лопатите всю таблицу построчно с жутким апдейтом другой таблицы.

Попробуйте так:
Код: 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.
28.
29.
30.
31.
32.
33.
34.
35.
begin tran;

if object_id('tempdb..#t') is not null
 drop table #t;

create table #t (MATERIALID int primary key, MATERIALID_FIRST int);

with m as
(
 select
  MATERIALID,
  min(MATERIALID) over (partition by RATE, TITLE, RESCODE) as MATERIALID_FIRST,
  count(*) over (partition by RATE, TITLE, RESCODE) as c
 from
  MATERIAL
)
update am
 set
  MATERIALID = m.MATERIALID_FIRST
output
 m.MATERIALID, m.MATERIALID_FIRST into #t
from
 m join
 ASSEMBL_YMATERIAL am on am.MATERIALID = m.MATERIALID
where
 m.c > 1;

delete m
from
 #t t join
 MATERIAL m on m.MATERIALID = t.MATERIALID
where
 t.MATERIALID > t.MATERIALID_FIRST;

commit;
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708851
Владимир Затуливетер
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pavell450,

Дополнительно к ответу invm, удостоверьтесь что следующий индекс у вас присутствует на таблице, а то судя по плану его нет.

Код: sql
1.
create index IDX_ASSEMBLY_MATERIAL_MaterialId on dbo.ASSEMBLY_MATERIAL ( MaterialId )
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708855
Владимир Затуливетер
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Еще вариант

Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
create table #tmpMaterialsForDelete ( MaterialId int primary key with (ignore_dup_key = on) );

with cteData
as (
    select *
         , first_value(MaterialId) over (partition by RATE, TITLE, RESCODE order by MaterialId) as MinMaterialId      
    from dbo.MATERIAL
)
update am
set MATERIALID = d.MinMaterialId
    output Deleted.MaterialId into #tmpMaterialsForDelete ( MaterialId )
from dbo.ASSEMBLY_MATERIAL am
    join cteData d on d.MaterialId = am.MaterialId
where am.MATERIALID != d.MinMaterialId

delete from dbo.Material where MaterialId in ( select MaterialId from #tmpMaterialsForDelete )



с тестовыми данными:
Код: 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.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
53.
54.
55.
56.
57.
use tempdb
go

create table dbo.Material ( 
    MaterialId int not null primary key
  , RATE int
  , TITLE varchar(128)
  , RESCODE int
);

insert into dbo.Material (MATERIALID, RATE, TITLE, RESCODE)
values
 (1, 1, 'test', 1 ),
 (2, 1, 'test', 1 ),
 (3, 1, 'test2', 1),
 (4, 1, 'test2', 1)
go

create table dbo.ASSEMBLY_MATERIAL (
    Id int identity not null primary key
  , MaterialId int not null
  , SomeData varchar(200) null
)

create index IDX_ASSEMBLY_MATERIAL_MaterialId on dbo.ASSEMBLY_MATERIAL ( MaterialId )
go

insert into dbo.ASSEMBLY_MATERIAL ( MaterialId, SomeData )
values (1, 'a'), (2, 'b'), (3, 'aa'), (4, 'bb'), (4, 'cc')
go

create table #tmpMaterialsForDelete ( MaterialId int primary key with (ignore_dup_key = on) );

with cteData
as (
    select *
         , first_value(MaterialId) over (partition by RATE, TITLE, RESCODE order by MaterialId) as MinMaterialId      
    from dbo.MATERIAL
)
update am
set MATERIALID = d.MinMaterialId
    output Deleted.MaterialId into #tmpMaterialsForDelete ( MaterialId )
from dbo.ASSEMBLY_MATERIAL am
    join cteData d on d.MaterialId = am.MaterialId
where am.MATERIALID != d.MinMaterialId

delete from dbo.Material where MaterialId in ( select MaterialId from #tmpMaterialsForDelete )


select * from dbo.Material
select * from dbo.ASSEMBLY_MATERIAL

go

drop table dbo.Material;
drop table dbo.ASSEMBLY_MATERIAL;
drop table #tmpMaterialsForDelete;
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39708997
pavell450
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
PizzaPizza,
выполняется не часы, быстрее :-)
1:32:29
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39709529
PizzaPizza
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pavell450PizzaPizza,
выполняется не часы, быстрее :-)
1:32:29

Очень долго для десятков тысяч строк.
Очевидно, где то проблема на стороне дизайна или обслуживания сервера.
Не рекомендую вам вмешиваться в работу сервера если это не ваша зона ответственности - вслепую можно убить базу.
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39709653
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pavell450,

Assembly_material большая таблица?
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39709838
pavell450
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
TaPaKpavell450,

Assembly_material большая таблица?

165 000 записей
...
Рейтинг: 0 / 0
Удаление дубликатов - страшно долго
    #39709840
TaPaK
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
pavell450TaPaKpavell450,

Assembly_material большая таблица?

165 000 записей
удаление ваших 30к записей рисует 5млрд чтений на эту таблицы, продолжайте развлекаться переписываниями запросов на красивые
...
Рейтинг: 0 / 0
18 сообщений из 43, страница 2 из 2
Форумы / Microsoft SQL Server [игнор отключен] [закрыт для гостей] / Удаление дубликатов - страшно долго
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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