MySQL優化(1):欄位的設計

来源:https://www.cnblogs.com/xuyiqing/archive/2020/03/10/12456830.html
-Advertisement-
Play Games

Web項目中,當Java或者Go等語言速度提升到瓶頸的時候,我們需要關心MySQL的優化 可以優化的方面有很多:設計表、負載均衡、讀寫分離、SQL語句優化等 (1)IP地址設計 例如我們需要存儲IP地址:192.168.1.1 第一反應是選用VARCHAR(15);但是更好的方式是INT UNSIG ...


Web項目中,當Java或者Go等語言速度提升到瓶頸的時候,我們需要關心MySQL的優化

可以優化的方面有很多:設計表、負載均衡、讀寫分離、SQL語句優化等

 

(1)IP地址設計

例如我們需要存儲IP地址:192.168.1.1

第一反應是選用VARCHAR(15);但是更好的方式是INT UNSIGNED(占用四個位元組)

因為:IP地址可以很容易地轉換為無符號整數

仔細觀察IP地址,四部分都是0-255的數字,1個位元組(8位)恰好可以表示0-255的整數

而MySQL有函數:inet_aton():地址轉成數字,inet_ntoa():數字轉成地址

示例:

SELECT INET_ATON('192.168.0.1')

結果:3232235521

SELECT INET_NTOA("3232235521")

結果:192.168.0.1

INT UNSIGNED占用位元組少於VARCHAR(15),並且整數查詢效率更高(代價是需要使用轉換函數)

總結:在設計欄位的時候,儘量使用整數來表示字元串

 

(2)關聯表設計

整型的優勢:固定存儲空間,通常是少量空間

例如:MySQL內部的枚舉和集合類型:

enum(男,女,未知)

insert into user(gender) values(男)

這句話在MySQL中實際存儲的是1,這就是最典型的把字元串存成整數

註意:實際中,很少使用mysql的enum和set,因為維護成果過高

比如性別需要把未知改為人妖,需要執行alter table modify column操作,需要獨占整張表,檢查記錄性別值的合法性

如果一定要使用這種方式:關聯表,欄位id,title,存儲1,男,2,女。這種方式使用較為廣泛

但是,比如家庭地址這樣的字元串,是無法改成整型的,不能強行操作

 

(3)金額存儲

金額的存儲對數據的精度要求較高,按理來說要使用DECIMAL()

例如DECIMAL(10,2):有2位小數的定點數

實際中有另一種操作:INT或BIGINT,這時候為了精度不丟失,採用”分“為單位(12.51元記錄為1251)

電腦中小數是無法做到不損失精度的,但是金額較特殊,固定了兩位小數,所以可以採用這種方式

而且編程中,整數的計算相對於小數較為方便

DECIMAL也有擅長的地方,比如存儲大數:123456789123456789

這時候不可以使用INT,只能使用BIGINT或者DECIMAL

 

註意:這裡為什麼我們不選擇浮點數DOUBLE和FLOAT呢?因為浮點數會導致精度丟失

原因:浮點數占用固定的存儲空間,無論存儲多大的數,空間是一定的;但是定點數空間會隨著數字變大而增加

由此引出了定長類型和變長類型:

定長類型:存儲空間固定(INT、FLOAT、DOUBLE、CHAR、DATE、TIME、DATETIME、YEAR、TIMESTAMP)

變長類型:存儲空間可變(VARCHAR、DECIMAL、TEXT)

註意:只有定長類型才會有損失精度的問題,定長類型效率較高

結論:在乎存儲空間採用定長類型,在乎存儲精度採用變長類型

 

(4)TEXT和VARCHAR的選擇

TEXT:通常感覺存儲容量較大,其實最大容量和VARCHAR的最大容量幾乎一樣

但是,TEXT是獨立存儲的,不占用欄位的總空間,但是VARCHAR占用欄位總空間,通常總空間是65535位元組

結論:更大的數據還是採用TEXT更好

更大的數據類型有LONGTEXT,可以用於選擇

 

(5)欄位設計的原則

1.儘可能選擇小的數據類型,這條無需多說

2.儘可能使用NOT NULL,因為資料庫不需要判斷是否為NULL,NULL在MYSQL中的存儲和運算更麻煩:

NULL參與常規運算的結果都是NULL,當判斷是否為空的時候,必須採用IS NULL和IS NOT NULL

MYSQL中每條記錄會使用到額外的存儲空間,用於表示每個欄位是否為NULL

通常使用一個特殊的數據來占位,比如我要表達NULL通常設置為空字元串或者0

這種情況又會出現問題,比如成績欄位,0代表沒有的話無法區分0分的學生,所以可以採用-1,消除歧義

3.欄位註釋要完整:gender int comment '性別'

4.單張表的欄位數量不宜過多,通常最多二三十個;數量過多通常會出現某個業務邏輯只是用其中一部分,浪費性能

5.預留欄位,比如field1 int field2 varcahr等等;後期項目如果需要更改表結構,這樣做會方便很多

 

(6)關聯表的設計

一對一:一條記錄的欄位較多,分佈到多個表中存儲

例如學生表,基礎信息:姓名、身高、班級,還有一些不常用的數據:籍貫、家庭成員等信息

這時候應該設計基礎信息一張表,不常用數據一張表,使用相同的主鍵來表示

 

一對多:在多的一端使用關聯欄位,關聯一端的主鍵

例如文章和分類表,分類是一端,文章是多端;那麼在文章表中需要有一個分類ID的欄位做關聯

 

多對多:使用中間表來實現

例如文章和標簽,多對多,那麼就需要一張表,欄位至少有ID、文章ID、標簽ID,每一條記錄代表一個關聯

 

(7)範式

第一範式:欄位的原子性,不可再分割

關係型資料庫預設滿足第一範式,MYSQL滿足

但也可以強行做:比如一個時間欄位,同時寫入開始時間和結束時間,這就不合理

一個容易出現的問題:(6)中的例子,文檔和標簽的設計中:如果我為了省事,不引入第三張表,而是在文章表中用一個欄位標簽IDs欄位(例如存入1,2,3)

這種情況很常見,是不合理的做法,在更新的時候會出現很多問題,需要把逗號拆開處理,而且無法建索引

除非是類似日誌系統,存入後不再維護,那麼可以使用這種方式

 

第二範式:滿足第一範式後,消除對主鍵的部分依賴(A欄位可以確定B欄位,那麼B欄位依賴A欄位)

主鍵:可以唯一標識記錄的欄位或者欄位集合

部分依賴:如果某個欄位依賴複合主鍵的一部分欄位,稱之為對主鍵的部分依賴

 

例如一個課程信息表,欄位有:老師,性別,班級,教室,時間,但是不存在ID

這時候需要我們選一個主鍵,這裡面每一個欄位都不能作為主鍵

老師和班級同時可以作為一個主鍵(複合主鍵)

但是性別對主鍵是部分依賴,如何消除呢?

 

部分依賴的產生必須是複合主鍵,那麼增加一個ID即可消除對主鍵的部分依賴

 

第三範式:第二範式的基礎上,消除對主鍵的傳遞依賴

傳遞依賴:C依賴於B,B依賴於主鍵,那麼C對主鍵存在傳遞依賴關係

上門的例子:性別依賴於老師,老師依賴於ID,那麼存在傳遞依賴關係

消除方式:將獨立數據單獨建表,使用關聯欄位進行存儲

例子中,建立一個單獨的表,記錄老師和性別的關係

 

總結:獨立數據獨立建表;表中存在與業務邏輯無關的ID主鍵;表之間的關係由關聯欄位(或關聯表)進行表示

通俗來講:我們建表中,基本都是滿足三大範式的


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

-Advertisement-
Play Games
更多相關文章
  • 1. 和用戶級相比,核心級線程有什麼不同? 在用戶級線程中,根據TCB(線程式控制制塊)切換用戶棧, 而核心級線程是,根據TCB(線程式控制制塊)切換一套棧,切換用戶棧和內核棧 2. 用戶棧和內核棧之間的關聯 進入內核棧的唯一方法是中斷 例子: 3. 開始內核中的切換 switch_to 4. 內核線程sw ...
  • 問題: 安裝了Wkhtmltopdf後,在odoo中列印出的報表顯示為已損壞。 odoo發出了一個警告提示版本不對,需要安裝qt補丁。 2020-03-10 01:53:27,152 9236 WARNING warehouse_management odoo.addons.base.models. ...
  • MRAM技術MRAM或磁性隨機存取存儲器使用1晶體管–1磁性隧道結(1T-1MTJ)架構,其中鐵磁材料的磁性“狀態”作為數據存儲元素。由於MRAM使用磁性狀態進行存儲(而不是隨時間推移而“泄漏”的電荷),因此MRAM可以提供非常長的數據保留時間(+20年)和無限的耐用性。切換磁極化(Write Cy ...
  • 不管是 Windows 電腦還是 Linux 電腦,在使用的過程中,或多或少都會留下很多重覆的文件。這些文件不僅會占用我們的磁碟,還會拖累我們的系統,所以,很有必要幹掉這些重覆的文件。 本文將介紹 6 種方法找到系統里的重覆文件,讓你快速釋放硬碟空間! 1. 使用 diff 命令比較文件 在我們平常 ...
  • 存儲引擎: 早期的時候,存在如何選擇MyISAM和Innodb? 現在,Innodb不斷地發展完善,成為了主流的存儲引擎。 因此5.5之後的mysql,無腦選擇Innodb即可。 MYSQL中的數據,索引以及其他的對象,是如何存儲的,是一套文件系統的實現。 MYSQL支持很多的存儲引擎,使用 SHO ...
  • mysql調優 1.選擇合適的存儲引擎 + 經常用來讀的表使用myisam引擎 + 其餘的表都使用innodb引擎 2.SQL語句調優(儘量避免全表掃描) + 在select where order by常涉及到的欄位上建立索引 + where語句中不使用 !=,否則將放棄使用索引進行全表掃描 + ...
  • 一、Mysql常見筆試題 1、Mysql 中有哪幾種鎖? (1)表級鎖:開銷小,加鎖快。不會出現死鎖,鎖定粒度大,發生鎖衝突的概率高,併發度低。 (2)行級鎖:開銷大,加鎖慢。會出現死鎖,鎖定粒度小,發生鎖衝突的概率低,併發度高。 (3)頁面鎖:開銷時間、加鎖時間、鎖定粒度在 表級鎖 與 行級鎖 之 ...
  • 索引的概念 不使用索引,要操作某些行時,需要遍歷遍歷整張表來找到匹配的行,很花時間,且有點耗資源。 書:目錄=>快速定位到指定章節,不用一頁一頁地找 資料庫:索引=>快速定位到指定記錄,不用遍曆數據表去找,索引相當於數據表的目錄 索引的優缺點 提高查詢效率,尤其是記錄數超級多的時候,查詢速度提升極大 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...