2012-05-22 281 views
4

我有一個緩慢的表演查詢,並希望有人在SQL更多的知識也許能幫助我提高性能:刪除與WHERE - 日期,時間和字符串比較 - 很慢

我有2個一個源和一個普通的表,我加載一些數據,其中包含一個日期,一個時間和字符串(這是一個服務器名稱),加上一些..

源表可以包含40k +行(它有30個奇數列(255)/(最大)

我使用下面的查詢來刪除來自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)'

的源字段是格式爲:

  • 服務器名的varchar(255)IE SN1234
  • 日期VARCHAR(255)IE 2012- 05-22
  • 時間VARCHAR(255)IE八時12分21秒

的通用字段是格式爲:

  • 服務器名的varchar(255)IE SN1234
  • 日期日期IE 2011-08-10
  • 時間時間(7) 14:25:34.0000000

感謝

+1

哪個表是哪個?兩個標籤都說'Source' ...以及爲什麼一張表將日期/時間數據存儲爲大量字符串?他們的確切格式是什麼?我們無法猜測這些事情。請向我們展示一些示例數據... –

+2

爲什麼在日期和時間字段中使用varchar(255)? – MichelZ

+0

由於logparser和我們使用它的方式,Source表將這些存儲爲varchars。我更新了公共表格格式的帖子。 也在旁邊添加了一個示例。希望這有助於 – 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

SourceDate和Source.Time的索引不會真正起到幫助作用,因爲轉換仍然會發生。 –

+0

@Aaron,同意了。 –

0

刪除不必要的轉換將有助於很多,如Aaron的答案中所述。您也可以考慮在日誌表頂部創建一個索引視圖,因爲您可能在該模式中沒有太大的靈活性,或者從日誌解析器插入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可以在不破壞其日誌解析器的情況下更改模式,則計算列絕對是理想的。好點的亞倫。 –