資料庫設計---關於建表的時候選擇橫標和豎表(縱表)的一點思考

来源:http://www.cnblogs.com/wy123/archive/2017/04/07/6677073.html
-Advertisement-
Play Games

本文出處:http://www.cnblogs.com/wy123/p/6677073.html 在做數據統計類資料庫設計的時候,在考慮數據存儲的時候,經常會遇到邏輯上同一個BusinessID對應多個數據點的情況,比如工資表中的員工ID以及各項工資信息,財務表中的各個報表Id和多個數據點之間的信息 ...


 

本文出處:http://www.cnblogs.com/wy123/p/6677073.html 

 

在做數據統計類資料庫設計的時候,在考慮數據存儲的時候,經常會遇到邏輯上同一個BusinessID對應多個數據點的情況,
比如工資表中的員工ID以及各項工資信息,財務表中的各個報表Id和多個數據點之間的信息
面對這種情況,如何來設計表結構,是橫表,還是豎表,各有那些優缺點,本文將做一個粗淺的分析。

 

橫標和豎表的表現形式

日常生活中也有很多類似的例子,先用一個Excel畫一個例子,比如工資表
這麼做就是“橫表”,特點是,一個ID對應所有的值信息,以行Key-Value1-Value2-Value3的方式存儲

如下是豎表(縱表),特點是每行僅存儲該ID的某一個類別欄位的值,以行的方式存儲Key-Value的方式存儲

 

橫標和豎表的設計示例

  下麵通過一個具體的例子來說明橫標和豎表的一些特點

--橫標
CREATE TABLE HorizontalTable
(
    Id                int identity(1,1),
    BusinessId        varchar(50)         ,
    CategoryVal1    varchar(20)         ,
    CategoryVal2    decimal(20,5)     ,
    CategoryVal3    datetime         ,
    CategoryVal4    varchar(20)         ,
    CategoryVal5    varchar(20)         ,
    CategoryVal6    varchar(20)
)
insert into HorizontalTable  values ('BH000001','value1',89.12,'20170406','abc4','abc5','abc6')
insert into HorizontalTable  values ('BH000002','value2',99.11,'20170407','abc4','abc5','abc6')

--豎表
CREATE TABLE VerticalTable
(
    Id                int identity(1,1),
    BusinessId        varchar(50),
    CategoryKey        varchar(20),
    Val                varchar(20)
)
insert into VerticalTable values ('BH000001','CategoryKey1','values1')
insert into VerticalTable values ('BH000001','CategoryKey2',89.12)
insert into VerticalTable values ('BH000001','CategoryKey3','20170406')
insert into VerticalTable values ('BH000001','CategoryKey4','abc4')
insert into VerticalTable values ('BH000001','CategoryKey5','ab5')
insert into VerticalTable values ('BH000001','CategoryKey6','ab6')
insert into VerticalTable values ('BH000002','CategoryKey1','values2')
insert into VerticalTable values ('BH000002','CategoryKey2',99.12)
insert into VerticalTable values ('BH000002','CategoryKey3','20170407')
insert into VerticalTable values ('BH000002','CategoryKey4','abc4')
insert into VerticalTable values ('BH000002','CategoryKey5','abc5')
insert into VerticalTable values ('BH000002','CategoryKey6','abc6')

橫表中的數據:

豎表中的數據

  

可能實際應用中,要比這個示例中的情況更加複雜,那麼在設計表結構的時候,如何選擇橫標或者豎表?
首先來看橫標的特點

對於橫表
  1,同一個Key值對應的列是固定的,比如,比如HorizontalTable中有6個欄位
  2,各個欄位的值是自由的,比如HorizontalTable中的CategoryVal1是varchar類型的,CategoryVal2是decimal的
  3,表中並不存儲描述性欄位本身(相比縱表)
  4,相比豎表,存儲同樣多的數據,行數要少
對於豎表
  1,同一個Key值對應的列是動態的,因為是按照行存儲的,可以存儲成Key1—Value1,Key1—Value2,Key1—Value3的方式存儲
  2,欄位的類型是固定的,但是類似是要相容的,不能有個性化的欄位,比如VerticalTable中的CategoryKey+Val,因為固定了這麼一個欄位
  3,表中需要存儲描述欄位本身(相比橫標),要根據BusinessKey值的不同,重覆存儲CategoryKey
  4,相比橫表,存儲同樣多的數據,行數要多

綜上可以看出,
  橫標的優點:橫標的有點事顯示的較為清晰直觀,同時在欄位的選擇上更為科學合理,具體的欄位可以根據具體情況劃分欄位類型,
  橫標的缺點:不方便擴展和公用,也就是說設計了一張橫標,只能在固定的某一種特定的相對不變的場景下使用,
        比如加欄位,或者類似的業務想公用一張橫表,都有局限

  豎表的優點:最大的特點是可以靈活擴展存儲的內容,同時具有一定的公用性
        因為豎表的存儲結構不受欄位個數的限制,可以存儲具有一定共性的業務數據。
  豎表的缺點:豎表的欄位類型要相容,比如橫標可以根據具體的值設計成varchar,decimal,datetime等,
        橫標為了相容以上欄位類型,只能設計成varchar的,可能會浪費一定的空間

 

  橫標和豎表主要考慮的是擴展性和共同性,對於顯示方式問題,個人認為倒是問題不大,無非是行轉列和列轉行的問題
  如下是一個將上述設計的橫表轉豎表和豎表轉橫標的示例,也不複雜,因此說,顯示的問題不是大問題

select * from HorizontalTable
--列轉行
;WITH HorizontalCET
AS
(
    SELECT Id,BusinessId,CategoryVal1,
            cast(CategoryVal2 as varchar(20)) as CategoryVal2,
            cast(CategoryVal3 as varchar(20)) as CategoryVal3,
            CategoryVal4,
            CategoryVal5
    FROM HorizontalTable
)
SELECT Id,BusinessId,ColumnName,ColumnVal
FROM HorizontalCET
UNPIVOT (ColumnVal FOR ColumnName IN 
            (CategoryVal1,
            CategoryVal2,
            CategoryVal3,
            CategoryVal4,
            CategoryVal5)
        ) tmp

--列轉行
select * from VerticalTable
SELECT * FROM 
(
    select BusinessId ,
           CategoryKey,
           Val 
    from VerticalTable
)t
 PIVOT( MIN(Val) FOR CategoryKey IN (CategoryKey1,
                                    CategoryKey2,
                                    CategoryKey3,
                                    CategoryKey4,
                                    CategoryKey5,
                                    CategoryKey6)
)a

  

 

關於橫表和豎表的性能問題

  關於性能問題,很難一概而論,還要結合具體的情況作分析,比如查詢方式,查詢數據了,索引結構等等都有一定的關係。
  錶面上看,豎表存儲了大量冗餘的數據,浪費了一定量的磁碟空間是事實,但是極端情況下橫表也有可能造成極大的空間浪費
  瞭解SQL Server的同學肯定知道,
  SQL Server中正常來來說是行存儲,一行數據不能跨頁存儲(當然forwarded存儲方式的數據除外,有機會說這個),
  SQL Server的最小存儲單位是頁(Page),一個頁的大小是8kb,除去page信息固定占用的空間之外是8060個位元組,
  每一行固定的一行數據除了數據自身占用的空間外,至少(不是一定,表結構越複雜占用的額外空間越大)還要占用1+1+2+2+1=7個位元組

  對於寬表,一旦欄位長度達到一定的程度,
  比如每行長度為800個位元組,理論上將,在一個page上,存儲9行記錄之後,還剩餘800位元組的空間(具體剩餘多少跟表結構有關,這裡只是舉例說明),
  對不起,第十行數據來了已經存不進去了,只能新開頁面分配存儲空間,這樣,當前這個頁面就浪費了800位元組的存儲空間
  反觀豎表,因為存儲的數據行都非常短,即便發生上述情況,也只會浪費很少的一點數據空間(小於一行數據的空間)
  極端情況下會更加有意思,參考這個http://www.cnblogs.com/studyzy/archive/2008/11/27/1342003.html

   

  有上述可見,對於橫表和豎表,不管是設計上還是存儲上,優點和缺點都是看站在哪個角度來看的,
  從一個角度來看是有點,從另外一個角度看就可能會變成缺點,只有捨棄一部分,根據實際情況權衡之後做出取捨。
  凡事無絕對,適合即可。

 

總結:

  本文從適應場景、存儲、性能等方面粗淺第分析了表設計時候橫標和豎表的特點和優缺點,
  具體設計的時候可綜合考慮,做出合理的選擇。
  另外,本文肯定還有沒有預計或者說想到的情況以及評估方向,也希望有想法的同學補充,謝謝。

 

    


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 相信 strings.xml 已經是大家在 Android 開發中最熟悉的文件之一了,但其實它也有很多需要註意的地方和一些小技巧,知道了這些可以讓你的 Android 應用更加規範易用,大家來看看吧。: ) 不要復用 這一條可能很多人會有不同的意見,因為廣為流行的編程理念就在教導我們要復用代碼,當然 ...
  • 頂部Analyze菜單中選擇Run Inspection by Name 在彈出的輸入框中輸入unused resources ...
  • 推薦地址:https://developer.apple.com/app-store/review/guidelines/cn/ 目錄 1.條款與條件 2.功能 3.元數據 4.位置 5.推送通知 6.游戲中心 7.廣告 8.商標與商品外觀 9.媒體內容 10.用戶界面 11.購買與貨幣 12.抓取 ...
  • 轉載請註明出處:http://www.cnblogs.com/cnwutianhao/p/6676121.html 序言 Android 用甜點作為它們系統版本的代號的命名方法開始於 Andoird 1.5 發佈的時候。作為每個版本代表的甜點按照26個英文字母順序的原則進行命名:紙杯蛋糕,甜甜圈,松 ...
  • OpenCV是一個基於BSD許可(開源)發行的跨平臺電腦視覺庫,可以運行在Linux、Windows、Android和Mac OS操作系統上。它輕量級而且高效——由一系列 C 函數和少量 C++ 類構成,同時提供了Python、Ruby、MATLAB等語言的介面,實現了圖像處理和電腦視覺方面的很 ...
  • 轉載請標明出處 "http://www.cnblogs.com/yxx123/p/6675567.html" 防止連續點擊的實現方式有很多種,比如,在所有的onclick裡面加上防多次點擊的代碼,或者定義一個新的OnClickListener,在裡面加上防多次點擊的代碼,然後項目中的所有OnClic ...
  • 最近的項目要用到一個線上報告的下載,於是完成後自己在理一下思路,大體的實現了我要得需求。 話不多說,直接上代碼 首先,取到網路文件的鏈接,進行判段是否需求再次下載還是直接打開 #pragma mark 下載報告 //// 第一步 //是否下載還是打開文件 - (void)downloadPDF:(N ...
  • Windows下MongoDB的下載、安裝以及對應的windows服務的創建 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...