google code prettify

2021年8月19日 星期四

[SQL Server] 先思考後實作,以儲存圖片檔案為例

最近因專案的需求,資深developer要求將檔案轉成Base64,並存到資料庫。後續再進一步了解儲存欄位被設定成什麼資料類型??結果是image。在學校考試通常有標準答案,但出了社會就必須靠自己求證best solution。這一篇,主要是說明那些資料型態已不能使用及相關議題

Q1.思考資料型態是否正確?
A:用image關鍵字去查microsoft,就會得知SQL Server 的未來版本將會移除 ntext、text 及 image 資料類型,看到這裡,並不是要去跟前輩理論對錯,而是你會發現,過去都是先做再說,也不管對或錯,下一個專案就會沿用過去的知識繼續錯下去。

Q2.在電子商務網站,將檔案轉存Base64並存到資料庫跟存檔案路徑,哪一個比較合適?
A:就過去的開發經驗我會選擇路徑,但這不足為據。而是要站在不同的角度去思考。
  • 查詢資料庫的效能跟I/O有關,所以大流量的網站都會做balance,減少負擔。白話一點,寧願保存用戶購買紀錄占用掉I/O,而不是用來賽檔案。
  • 如果站在Infra的角度,知道Microsoft Server DFS,也會選擇存檔案路徑,並做balance
  • 如果站在DBA的角度,知道Microsoft File Table,也就有另一種solution,不會選存Base64
這裡有趣的地方在於,純開發的developer,可能很少聽過DFS或File Table,通常比較在乎前後端用什麼架構。

Q3.除了將Base64檔案存資料,又用Guid當PK,合適嗎?
A:資料結構-搜尋樹,會提到演算法對應的時間複雜度,就定序而言,如果使用 int, bigint 這類具有快速判斷順序的資料型態作為 Clustered Index 的材料,至少也有Log2N的速度,而不是時間複雜度N,(阿鬼~你還是說中文好了0.0a)

以下截取黑暗大的文章
1.將GUID PK設成非叢集索引利大於弊 
2.資料表欠缺叢集索引就會形成Heap Table,弊大於利。所以,最好的折衷方案就是「GUID PK設成非叢集索引,並另外增設叢集索引」,而這個額外的叢集索引,自動跳號整數會是首選。如此我們降低GUID PK導致索引破碎的風險,自動跳號叢集索引避免新增資料造成索引破碎,而叢集索引讓資料表可以透過索引重建重組改善破碎狀況,同時避開索引破碎及Heap Table陷阱。
綜合以上,來段CREATE SCRIPT示意:
CREATE TABLE [dbo].[MiniFlow](
     [SeqNo] [int] IDENTITY(1,1) NOT NULL,
     [FlowId] [uniqueidentifier] NOT NULL,
     [FormCode] [varchar](4) NOT NULL,
     [FormNo] [varchar](16) NOT NULL,
     [Subject] [nvarchar](256) NOT NULL,
    CONSTRAINT [PK_MiniFlow] PRIMARY KEY NONCLUSTERED
    (
         [FlowId] ASC
    )
)
GO
CREATE CLUSTERED INDEX [IX_MiniFlow] ON [dbo].[MiniFlow]
(
     [SeqNo] ASC
)
GO
  1. PK增設SeqNo INT,以IDENTITY(1,1)設定自動跳號
  2. FlowId為GUID是MiniFlow資料表的Primary Key,但設定時加上NONCLUSTERED指定為非叢集索引
  3. 利用CREATE CLUSTERED INDEX將SeqNo建為叢集索引
---------------------------------------------------------------------------------

翻成白話文,請不用PK找資料,請用另一個Index定序SeqNo找資料,至少也有Log2N的速度
總結CreateTable 時
1.如果使用int, bigint定序當PK,具有快速判斷順序的資料型態作為 Clustered Index 
2.如果使用Guid當PK,一定要另外設定CLUSTERED INDEX,避免Table Scan




Reference

沒有留言:

張貼留言