我有一個數據庫表,以每秒/每設備約4條記錄的速度收集記錄。這張桌子變得相當快。當設備完成其任務時,另一個進程將遍歷所有記錄,執行一些操作,將它們合併爲5分鐘的塊,壓縮並存儲它們以備後用。然後它刪除該表中該設備的所有記錄。用於臨時存儲數百萬條記錄的最佳SQL DB設計
現在有幾百萬個設備的記錄。我可以通過它們循環執行處理,但是當我嘗試刪除它們時,我超時了。有沒有辦法更快地刪除這些記錄?也許暫時關閉對象跟蹤?使用一些鎖暗示?設計會更好嗎?當它開始任務時,爲每個設備創建一個單獨的表格,然後在數據處理完成後再放下它?超時設置爲10分鐘。如果可能的話,我希望在10分鐘內完成該過程。
CREATE TABLE [dbo].[case_waveform_data] (
[case_id] INT NOT NULL,
[channel_index] INT NOT NULL,
[seconds_between_points] REAL NOT NULL,
[last_time_stamp] DATETIME NOT NULL,
[value_array] VARBINARY (8000) NULL,
[first_time_stamp] DATETIME NULL
);
CREATE CLUSTERED INDEX [ClusteredIndex-caseis-channelindex] ON [dbo]. [case_waveform_data]
(
[case_id] ASC,
[channel_index] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
CREATE NONCLUSTERED INDEX [NonClusteredIndex-all-fields] ON [dbo].[case_waveform_data]
(
[case_id] ASC,
[channel_index] ASC,
[last_time_stamp] ASC
)
INCLUDE ( [seconds_between_points],
[value_array]) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON PRIMARY]
的SQL Server 2008+的標準是DB平臺
更新2014年3月31日:
我已經開始下降,這似乎是有問題的路徑。這真的很糟嗎? 我正在創建一個存儲過程,該過程需要一個包含要附加數據的表值參數和一個包含設備唯一表名稱的varchar參數。這個存儲過程將檢查表的存在,如果它不存在,請使用特定結構創建它。然後它會插入來自TVP的數據。我看到的問題是我必須在SP中使用動態SQL,因爲似乎無法將表名作爲變量傳遞給CREATE或INSERT。另外,我讀過的每篇文章都說如何做到這一點...
不幸的是,如果我有一個表以4 /秒/設備的頻率獲得所有插入,即使對於case_id和channel_index上的聚集索引,特定case_id的表也需要17分鐘。所以試圖刪除它們需要大約25-30分鐘。這也會導致鎖定發生,因此插入開始花費更長和更長的時間,導致服務退後。甚至在沒有刪除發生時也會發生這種情況。 所描述的存儲過程旨在將插入從4/sec /設備減少到1/sec /設備,並且可以在完成時刪除表,而不是單獨刪除每個記錄。思考?
更新2 2014年3月31日
我不使用遊標或者你所想的任何循環。這裏是我用來循環記錄的代碼。這在運行但是可接受的速度:
using (SqlConnection liveconn = new SqlConnection(LiveORDataManager.ConnectionString))
{
using (SqlCommand command = liveconn.CreateCommand())
{
command.CommandText = channelQueryString;
command.Parameters.AddWithValue("channelIndex", channel);
command.CommandTimeout = 600;
liveconn.Open();
SqlDataReader reader = command.ExecuteReader();
// Call Read before accessing data.
while (reader.Read())
{
var item = new
{
//case_id = reader.GetInt32(0),
channel_index = reader.GetInt32(0),
last_time_stamp = reader.GetDateTime(1),
seconds_between_points = reader.GetFloat(2),
value_array = (byte[])reader.GetSqlBinary(3)
};
// Perform processing on item
}
}
}
我用它來刪除的SQL很簡單:
DELETE FROM case_waveform_data where case_id = @CaseId
這一行需要25+分鐘刪除一個百萬行
的樣本數據(value_array被截斷):
case_id channel_index seconds_between_points last_time_stamp value_array first_time_stamp
7823 0 0.002 2014-03-31 15:00:40.660 0x1F8B0800000000000400636060 NULL
7823 0 0.002 2014-03-31 15:00:41.673 0x1F8B08000000000004006360646060F80F04201A04F8418C3F4082DBFBA2F29E5 NULL
7823 0 0.002 2014-03-31 15:00:42.690 0x1F8B08000000000004006360646060F80F04201A04F8418C3F4082DBFB NULL
什麼有關刪除everyting比x分鐘歲以上的計劃作業的基礎上, first_time_stamp? –
如何標記要刪除的記錄的位標誌,然後在系統較安靜時再執行? – bhs
企業還是標準?如果企業,聽起來像分區切換的工作...... –