iT邦幫忙

0

如何設計SQL 表格來提升查詢非過往歷史資料的效能?

  • 分享至 

  • xImage

個人正在寫一個場地租借系統, 提前開放2週給人預約,
租借的過期紀錄要保留起來作系統或規則改善研究,
可想像隨營運時間, 歷史資料會越來越多,
實際上, 使用者只會預約近2週的場地借用時段(每天有15個時段),
1年下來 52週, 只有2週要讀取, 歷史包袱 50 週,
2年下來 52x2=104週, 也是只有2週要讀取, 歷史包袱 102 週;
3年下來 52x3=156週, 也是只有2週要讀取, 歷史包袱 154 週;
N 年下來, 可想而知的歷史包袱 (52N - 2) 週;
有率資料第1年結束, 佔比剩 4% = (2/50 )
有率資料第4年結束, 佔比剩不到 1% > (2 / 206),
何況不只一個場地項目, 光想到此就覺得糟糕了!

我有兩個想法, 想問的問題是第2個想法:

我第1個想法,
我想像用 NewTable 專放2週內的資料, OldTable 專放過期資料;
寫個Routine在凌晨時, 將資料從 NewTable 過期資料 搬到 OldTable.

我第2個想法, 只用1個Table,
但是多加一個 Flag 欄位, 欄位值 1 表示 New, 欄位值 0 表示 Old
雖然Flag 欄造成表格變更大,
但能對 SQL Server 是比較有效率查詢!
這欄位屬性要如何設置? 算是要 SQL Server 對 Flag 欄的做索引嗎?

====================================================================

目前, 用 SSMS 看到 測試 DB 的 測試 Table 的 某 int 欄 或 某 datetime 欄,
該「資料行屬性」只有「全文檢索規格」可能算有點相關的設置,
但直覺上應該跟我要解決的效能問題無直接相關,

後來在 google 到可以下指令, 讓該欄位索引化
CREATE CLUSTERED INDEX idx_V1 ON [dbo].Test_IdxPFM
測試 20.1 萬筆資料的讀取, 起來速度變快很多, 10-1000倍左右,
原理上我還沒深入去看, 而且, clustered index 只能設置一個欄位,
若想要索引化其他欄位或更多欄位,

法1. 假設純粹換另一個欄位索引化,
刪掉原 clustered index 欄位,
新增新欄位的 clustered index 設置,
因為, 1個 Table 限最多1個是 clustered index 欄位,

法2. 保留原 clustered index 欄位,
改新增其他欄位的 nonclustered index 設置,
CREATE NONCLUSTERED INDEX idx_V2 ON [dbo].Test_IdxPFM

註: 其他至少還有2種索引方式

Ext_Q1:
因為只有1000筆資料是要Select出來,
希望索引後,
這1000筆資料被要Select出來的花費時間,
應該是幾乎常數才對?

Ext_Q2:
若將這1000筆資料, Update 成預期 Select 時不會輸出的資料,
再Insert 該1000筆資料, 該新1000資料預期 Select 時會被輸出的資料,
好像也沒變慢回去, 是正常的嗎?
難道, CLUSTERED INDEX 或 NONCLUSTERED INDEX 系統會自動更新索引內容?
不用我每一次 Update / Insert 時,
手動 Delete / Create CLUSTERED INDEX 或 NONCLUSTERED INDEX 來更新索引內容?

Ext_Q3: 我懷疑測試資料不夠客觀、務實,
我的測試資料:
用 Transact SQL 的 while 語法加入測試資料,
前面 10 萬筆, 預期不會被 Select 輸出的資料,
接著 1000 筆, 預期會被 Select 輸出的資料,
再接 10 萬筆, 預期不會被 Select 輸出的資料,

有沒有什麼方法可以直接把系統上的資料給隨機換位?

Ps. 我是想用 C# 讀起來, 再隨機寫到另一個 New Test Table
或 2000筆 Select 不到資料, 配1筆 Select 要的資料, 寫到另一個 New Test Table

Ext_Q4,
延伸 Ext_Q3,
當我知道 Select 出來結果一定有1000筆,
不設 CLUSTERED INDEX 或 CREATE NONCLUSTERED INDEX 的情況下,
改用 Top(1000) 修飾 Select 的指令,
也發現會明顯改善效率!
想問的是若這1000筆預期會輸出的資料, 在 Table 的第1筆, 和 Table 的最後1筆,
是不是, 效率會整個 down 下來?

Ext_Q5:
在設置 clustered index 欄位或 nonclustered index 欄位後,
從那些欄位「資料行屬性」看不出有什麼變動?

用SSMS從該DB的右鍵選單的「編寫資料表的指令碼為」的「Create至」的「新增查詢編輯器視窗」的 SQL 指令內容,
看不出有什麼包含 CREATE CLUSTERED INDEX 或 CREATE NONCLUSTERED INDEX,

也就是, 我目前查不出 Table 的欄位是否存在有被設置 NONCLUSTERED INDEX 或 NONCLUSTERED INDEX的情況,
只有在下該欄位的 CREATE CLUSTERED INDEX 或 CREATE NONCLUSTERED INDEX 時,
SSMS 會警告有重覆了!
有沒有比較好的方式得知表格所有欄位被設 CLUSTERED INDEX 或 NONCLUSTERED INDEX 的情況?

Ext_Q6:
延伸 Ext_Q5 的查不到欄位被設 CLUSTERED INDEX 或 NONCLUSTERED INDEX 的情況下,
若撘配 DB 備份 或 複製,
會不會沒備到或複製到 CLUSTERED INDEX 或 NONCLUSTERED INDEX 的設置?

deh iT邦研究生 1 級 ‧ 2022-04-19 11:54:07 檢舉
沒多少資料不需要這樣搞。如果只是想練習DB的話,那就正規化+索引做一做。比起方案1,方案2加一個欄位bool是否為舊比較常見。最近用mongodb對上億筆資料進行一萬次查詢也就耗時1秒,一點點資料寫好不好也感覺不出來。
淺水員 iT邦大師 6 級 ‧ 2022-04-19 12:48:58 檢舉
直接在與時間有關的欄位加上索引的話呢?
這樣過期的話只是選擇時間範圍不同
不用更新資料表
天黑 iT邦研究生 5 級 ‧ 2022-04-19 17:00:54 檢舉
其實我覺得一個系統要活超過5年還有在使用,其實不容易,而且資料是有使用才有紀錄,如果使用率不高,資料量累積也不會太龐大
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 個回答

0
Peter
iT邦新手 4 級 ‧ 2022-04-19 13:00:04

我第1個想法,
我想像用 NewTable 專放2週內的資料, OldTable 專放過期資料;
寫個Routine在凌晨時, 將資料從 NewTable 過期資料 搬到 OldTable.

這是正確的做法,假設你每天會有一千萬筆資料寫入,一個月就是三億筆,這對SQL Server確實是會產生一點負擔,在資料量很大的時候,就算有建index,每次SELECT的Disk I/O還是很可觀的,因此定期搬資料,將報表功能(低頻)與業務功能(高頻)分開會是正確的做法。

0
海綿寶寶
iT邦大神 1 級 ‧ 2022-04-19 13:30:31

我覺得你想太早也想太多了

建議先想大概的資料庫設計
類似你樓下這篇

我要發表回答

立即登入回答