Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Microsoft SQL Server Новый топик    Ответить
 долгий update  [new]
нуб987
Guest
подскажите пожалуйста, что я делаю не так?
есть таблица, в которой нужно присвоить коды группам значений. Например:
idNameCode
1Иванов1
2Иванов1
3Иванов1
4Петров2
5Сидоров3
6Иванов1
7Петров2
8Петров2

Т.е. Иванов - это первая группа, Петров - 2-я, Сидоров - 3-я.

Вот пример запросов:
create table #Helper (
[id] [int] IDENTITY (1, 1) NOT NULL , -- код записи (на будущее)
Name nvarchar(255) NULL, -- некие значения (Иванов, Петров, Сидоров...)
Code int NULL -- группа
) on [PRIMARY]


print GetDate() -- засекаем время

declare
   @n int

set @n = 1
SET NOCOUNT ON

-- заполняем значениями
while @n <= 35000
   begin
   insert into #Helper
   (Name)
   values(rand(@n))

   set @n = @n + 1
   end

SET NOCOUNT OFF

-- создаем индекс на поле значений
CREATE  INDEX [IX_Helper_Name] ON [dbo].[#Helper]([Name]) ON [PRIMARY]

print GetDate() -- на заполнение таблицы и индекс уходит менее минуты

update #Helper -- это выполняется за час
set Code = aaa.Code
--select aaa.Code, #Helper.* -- это выполняется за секунду
from (
   -- "классический" вариант получения порядкового номера записи
   select distinct (select count(distinct Name) + 1 from #Helper u
         where u.Name < u2.Name
         ) as Code
      , u2.Name
   from #Helper u2
   ) as aaa, #Helper
where #Helper.Name = aaa.Name

print GetDate()

drop table #Helper


Проблема в том, что если апдейтить записи, присваивая им порядковые номера групп, то это выполняется около часа.
Но если вместо апдейта выполнить селект, набор данных возвращается примерно за секунду.
Индексов на редактируемом поле нет. Почему апдейт происходит так долго?

ПС. MSSQL2000
27 мар 14, 13:01    [15794227]     Ответить | Цитировать Сообщить модератору
 Re: долгий update  [new]
aleks2
Guest
Патамушто, думать надо, а не просто трясти.

мар 27 2014 3:12PM
мар 27 2014 3:12PM

(35000 row(s) affected)

(35000 row(s) affected)
мар 27 2014 3:12PM

какой, нахер, ЧАС?

create table #Helper (
[id] [int] IDENTITY (1, 1) NOT NULL , -- код записи (на будущее)
Name nvarchar(255) NULL, -- некие значения (Иванов, Петров, Сидоров...)
Code int NULL -- группа
) on [PRIMARY]

print GetDate() -- засекаем время

declare  @n int

set @n = 1
SET NOCOUNT ON

-- заполняем значениями
while @n <= 35000
   begin
   insert into #Helper
   (Name)
   values(rand(@n))

   set @n = @n + 1
   end

SET NOCOUNT OFF

-- создаем индекс на поле значений
CREATE  INDEX [IX_Helper_Name] ON [dbo].[#Helper]([Name]) ON [PRIMARY]

print GetDate() -- на заполнение таблицы и индекс уходит менее минуты

declare @nn table(Name nvarchar(255) primary key clustered, n int identity);
insert @nn(Name) select distinct Name from #Helper;

update u2 -- это выполняется за час
  set Code = aaa.n
  from @nn aaa inner join #Helper u2 on u2.Name = aaa.Name;

print GetDate()

drop table #Helper
27 мар 14, 13:14    [15794335]     Ответить | Цитировать Сообщить модератору
 Re: долгий update  [new]
Glory
Member

Откуда:
Сообщений: 104751
нуб987
Почему апдейт происходит так долго?

Ответ - в плане выполнения запроса

нуб987
Но если вместо апдейта выполнить селект, набор данных возвращается примерно за секунду.

И как выглядит этот "селект вместо апдейт" ?
27 мар 14, 13:15    [15794347]     Ответить | Цитировать Сообщить модератору
 Re: долгий update  [new]
aleks2
Guest
Если поточнее засечь:

2730 мс - заполнение

(35000 row(s) affected)

(35000 row(s) affected)

740 мс - обновление

create table #Helper (
[id] [int] IDENTITY (1, 1) NOT NULL , -- код записи (на будущее)
Name nvarchar(255) NULL, -- некие значения (Иванов, Петров, Сидоров...)
Code int NULL -- группа
) on [PRIMARY]

declare  @n int, @dt datetime

set @dt =  GetDate() -- засекаем время


set @n = 1
SET NOCOUNT ON

-- заполняем значениями
while @n <= 35000
   begin
   insert into #Helper
   (Name)
   values(rand(@n))

   set @n = @n + 1
   end

SET NOCOUNT OFF

-- создаем индекс на поле значений
CREATE  INDEX [IX_Helper_Name] ON [dbo].[#Helper]([Name]) ON [PRIMARY]

print datediff(ms, @dt, GetDate()) -- на заполнение таблицы и индекс уходит менее минуты
set @dt =  GetDate() -- засекаем время

declare @nn table(Name nvarchar(255) primary key clustered, n int identity);
insert @nn(Name) select distinct Name from #Helper;

update u2 -- это выполняется за час
  set Code = aaa.n
from @nn aaa inner join #Helper u2 on u2.Name = aaa.Name;

print datediff(ms, @dt, GetDate())

drop table #Helper
27 мар 14, 13:54    [15794655]     Ответить | Цитировать Сообщить модератору
 Re: долгий update  [new]
нуб987
Guest
aleks2
Патамушто, думать надо, а не просто трясти.
<...>
declare @nn table(Name nvarchar(255) primary key clustered, n int identity);
insert @nn(Name) select distinct Name from #Helper;

о таком варианте я в курсе (создать временную таблицу с счетчиком и перегнать в нее "distinct Name", автоматически получив номера групп). Но речь не о нем, а о том, что апдейт, приведенный в первом сообщении темы, выполняется за час. Тогда как такой же селект выполняется за пару секунд.
Т.е. неясно, чем вызвана такая задержка при апдейте. Никаких индексов на изменяемом поле нету. Почему так долго обновляются записи?
27 мар 14, 14:06    [15794739]     Ответить | Цитировать Сообщить модератору
 Re: долгий update  [new]
нуб987
Guest
Glory
И как выглядит этот "селект вместо апдейт" ?

вот так:
--update #Helper -- это выполняется за час
--set Code = aaa.Code
select aaa.Code, #Helper.* -- это выполняется за секунду
from (
   -- "классический" вариант получения порядкового номера записи
   select distinct (select count(distinct Name) + 1 from #Helper u
         where u.Name < u2.Name
         ) as Code
      , u2.Name
   from #Helper u2
   ) as aaa, #Helper
where #Helper.Name = aaa.Name
27 мар 14, 14:07    [15794751]     Ответить | Цитировать Сообщить модератору
 Re: долгий update  [new]
aleks2
Guest
нуб987
aleks2
Патамушто, думать надо, а не просто трясти.
<...>
declare @nn table(Name nvarchar(255) primary key clustered, n int identity);
insert @nn(Name) select distinct Name from #Helper;

о таком варианте я в курсе (создать временную таблицу с счетчиком и перегнать в нее "distinct Name", автоматически получив номера групп). Но речь не о нем, а о том, что апдейт, приведенный в первом сообщении темы, выполняется за час. Тогда как такой же селект выполняется за пару секунд.
Т.е. неясно, чем вызвана такая задержка при апдейте. Никаких индексов на изменяемом поле нету. Почему так долго обновляются записи?


Осподе! Ну чож тут загадочного?

Для обновления ВСЕГО - сервер сканирует #Helper и, следите за руками! при обновлении КАЖДОЙ строки #Helper сканирует DerivedTable aaa. На которой индексов НЕМА.

Вот и фся загадка. 35000 сканирований - это и есть час.

В прынципе, можно попытаться "вразумить" сервер. Но это нерентабельно.
27 мар 14, 14:21    [15794879]     Ответить | Цитировать Сообщить модератору
 Re: долгий update  [new]
нуб987
Guest
aleks2, а чего ж тогда селект такой быстрый?
27 мар 14, 14:26    [15794925]     Ответить | Цитировать Сообщить модератору
 Re: долгий update  [new]
Алексей Куренков
Member [заблокирован]

Откуда: Москва
Сообщений: 567
нуб987,

а может как здесь?

create table #Helper (
[id] [int] IDENTITY (1, 1) NOT NULL , -- код записи (на будущее)
Name nvarchar(255) NULL, -- некие значения (Иванов, Петров, Сидоров...)
Code int NULL -- группа
) on [PRIMARY]


print GetDate() -- засекаем время

declare
   @n int

set @n = 1
SET NOCOUNT ON

-- заполняем значениями
while @n <= 35000
   begin
   insert into #Helper
   (Name)
   values(rand(@n))

   set @n = @n + 1
   end

SET NOCOUNT OFF

-- создаем индекс на поле значений
CREATE CLUSTERED INDEX [IX_Helper_Name] ON [dbo].[#Helper]([Name]) ON [PRIMARY]

print GetDate() -- на заполнение таблицы и индекс уходит менее минуты

/*update #Helper -- это выполняется за час
set Code = aaa.Code
--select aaa.Code, #Helper.* -- это выполняется за секунду
from (
   -- "классический" вариант получения порядкового номера записи
   select distinct (select count(distinct Name) + 1 from #Helper u
         where u.Name < u2.Name
         ) as Code
      , u2.Name
   from #Helper u2
   ) as aaa, #Helper
where #Helper.Name = aaa.Name*/

declare @i int = 0
update #Helper
set @i = Code = @i + 1

print GetDate()

drop table #Helper
27 мар 14, 22:14    [15797573]     Ответить | Цитировать Сообщить модератору
Все форумы / Microsoft SQL Server Ответить