2012-05-22 3 views
4

У меня медленный запрос исполнительскую и надеялся кто-то с немного больше знаний в SQL может быть в состоянии помочь мне улучшить производительность:Удалить с WHERE - дата, время и сравнения строк - очень медленно

У меня есть 2 таблицы a Source и Common, я загружаю некоторые данные, которые содержат Date, Time и String (whch - имя сервера), плюс некоторые ..

Исходная таблица может содержать строки 40k + (имеет 30 нечетных столбцов , сочетание значений int, дат, времени и некоторых varchars (255)/(Max)

Я использую приведенный ниже запрос для удаления любых данных из Common, который находится в источнике:

'Delete from Common where convert(varchar(max),Date,102)+convert(varchar(max),Time,108)+[ServerName] in (Select convert(varchar(max),[date],102)+convert(varchar(max),time,108)+ServerName from Source where sc_status < 300)'

Источник Поля в этом формате:

  • ServerName VARCHAR (255) IE SN1234
  • Дата VARCHAR (255) IE 2012- 05-22
  • Время VARCHAR (255) IE 08:12:21

Общий Поля в этом формате:

  • ServerName VARCHAR (255) IE SN1234
  • Дата публикации IE 2011-08-10
  • Время Время (7) 14 т.е: 25: 34.0000000

Благодаря

+1

Какая таблица есть? Обе эти метки говорят «Источник» ... и почему одна таблица хранит данные даты/времени как массивные строки? Каков их точный формат? Мы не можем догадываться об этом. Пожалуйста, покажите нам пример данных ... –

+2

Почему вы используете поля varchar (255) для полей Date and Time? – MichelZ

+0

Исходная таблица хранит их как varchars из-за logparser и того, как мы его использовали. Я обновил сообщение для форматов Common Table. Также добавлен пример рядом с каждым. Надеюсь, что это помогает – TomEaton

ответ

5

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

DELETE c 
    FROM dbo.Common AS c 
    INNER JOIN dbo.Source AS s 
    ON s.ServerName = c.ServerName 
    AND CONVERT(DATE, s.[Date]) = c.[Date] 
    AND CONVERT(TIME(7), s.[Time]) = c.[Time] 
    WHERE s.sc_status < 300; 
+0

Это решение выглядит довольно хорошо. Главное - избегать конвертов и конкатений строк. Интересно, нужно ли конвертировать столбцы s.Date и s.Time. – bjorsig

+0

@bjorsig Если вы не сделаете это явно, это все равно сделает это как неявное преобразование. –

+0

Я попробую это и вернусь к вам. Спасибо :) – TomEaton

0

Все эти преобразования в VARCHAR(MAX) являются ненужными и, вероятно, замедляя Вас. Я хотел бы начать с чем-то вроде этого, вместо:

DELETE c 
from [Common] c 
WHERE EXISTS(
    SELECT 1 
    FROM Source 
    WHERE CAST([Date] AS DATE)=c.[Date] 
    AND CAST([Time] AS TIME(7))=c.[Time] 
    AND [ServerName]=c.[ServerName] 
    AND sc_status < 300 
); 
0

Что-то вроде

Delete from Common inner join Source 
On Common.ServerName = Source.ServerName 
and Common.Date = Convert(Date,Source.Date) 
and Common.Time = Convert(Time, Source.Time) 
And Source.sc_Status < 300 

Если это слишком медленно после этого, то вам нужны некоторые индексы, возможно на обеих таблицах.

+1

Индекс на 'Source.Date' и' Source.Time' на самом деле не поможет, так как преобразования все равно должны произойти. –

+0

@ Арон, согласился. –

0

Удаление ненужных преобразований поможет многое, что подробно описано в ответе Аарона.Вы также можете рассмотреть возможность создания индексированного представления в верхней части таблицы журналов, поскольку вы, вероятно, не имеете большой гибкости в этой схеме или вставляете DML из анализатора журналов.

Простой пример:

create table dbo.[Source] (LogId int primary key, servername varchar(255), 
    [date] varchar(255), [time] varchar(255)); 
insert into dbo.[Source] 
    values (1, 'SN1234', '2012-05-22', '08:12:21'), 
      (2, 'SN5678', '2012-05-23', '09:12:21') 
go 

create view dbo.vSource with schemabinding 
as 
    select [LogId], 
      [servername], 
      [date], 
      [time], 
      [actualDateTime] = convert(datetime, [date]+' '+[time], 120) 
    from dbo.[Source]; 
go 

create unique clustered index UX_Source on vSource(LogId); 
create nonclustered index IX_Source on vSource(actualDateTime); 

Это даст вам индексированный столбец DATETIME, на котором искать и значительно улучшить свои планы выполнения за счет выполнения некоторой вставки.

+0

Вероятно, вы должны иметь 'convert (datetime, [date] + '' + [time], 120)' в определении представления. Однако это будет очень дорогим видом для поддержания процесса массовой загрузки. Я бы предпочел добавить вычисляемый столбец в эту таблицу вместо всего этого материализованного представления, если процесс массовой загрузки может обрабатывать столбцы, которые он не может коснуться. –

+0

Исправлено, спасибо! Вычисленный столбец определенно будет идеальным, если OP может изменить схему, не нарушая его анализатор журналов. Хорошая точка Аарона. –

Смежные вопросы