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 欄的做索引嗎?


圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

2 則留言

0
leo19790301
iT邦新手 5 級 ‧ 2022-04-15 10:46:49

目前, 用 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 的設置?

Ans For Ext_Q5,

  1. 在 SSMS 的 該 Table 的「索引」目錄, 有列出 Create 的索引們

  2. 想刪特定索引, 在 SSMS 的 該 Table 的「索引」目錄 的 該特定索引的右鍵選單,
    執行「編寫資料表的指令碼為」的「Drop 至」的「新增查詢編輯器視窗」,
    就能帶出指令 Drop Index <你創的Index名稱> On <你創的Index的Table>

DB 下的 Table 資料表 含「索引」目錄,
DB 下的 View 檢視 也含「索引」目錄,
所以, 不只 Table 的欄位能「索引化」,
View 的欄位也能「索引化」

0
leo19790301
iT邦新手 5 級 ‧ 2022-04-18 09:01:32

針對先前『我第1個想法,
我想像用 NewTable 專放2週內的資料, OldTable 專放過期資料;
寫個Routine在凌晨時, 將資料從 NewTable 過期資料 搬到 OldTable.
』延申另一個同步性問題,

當資料從 NewTable 搬到 OldTable 時, 如果開放預約或查詢會不會有問題?

Case 預約:
因為資料是過期, 不管NewTable 或 OldTable 都不該也不會被預約成功,
應該不會變成問題!
更正確的, NewTable 上雖然都放近2週可預約, 但過期的還是可以判斷出可否被預約!

Case 查詢:
搬移 = Copy 完成 → 再 Delete 掉 NewTable 上被 Copy 的資料,

再 Copy 未完成時, Copy 到的資料, 會同時存在 NewTable 和 OldTable 兩邊,
變成好像有人重覆預約,
所以, Copy 時, 要停止查詢或檢查一些違規的規則,

再 Copy 未完成時, 突然斷電 或 Crash ,
也是問題!

另外, Copy 完成後, 突然斷電 或 Crash ,
變成沒完成 Delete,
也是問題!

結論:
本問題桃戰到 「可移動資料結構的設計」

Move != Copy + Delete
Move 未完成時, 要 Locked 其他動作,
但是, Copy 和 Delete 要依序開放!

我要留言

立即登入留言