什么影響了性能
數(shù)據(jù)庫設(shè)計對性能的影響
- 過分的反范式化為表建立太多的列
- 過分的范式化造成太多的表關(guān)聯(lián)
- 在OLTP環(huán)境中使用不恰當(dāng)?shù)姆謪^(qū)表
- 使用外鍵保證數(shù)據(jù)的完整性
MySQL基準(zhǔn)測試
什么是基準(zhǔn)測試
定義:
基準(zhǔn)測試是一種測量和評估軟件性能指標(biāo)的活動用于建立某個時刻的性能基準(zhǔn),以便當(dāng)系統(tǒng)發(fā)生軟硬件變化時重新進行基準(zhǔn)測試以評估變化對性能的影響
基準(zhǔn)測試是針對系統(tǒng)設(shè)置的一種壓力測試
基準(zhǔn)測試
直接、簡單、易于比較,用于評估服務(wù)器的處理能力
壓力測試
對真實的業(yè)務(wù)數(shù)據(jù)進行測試,獲得真實系統(tǒng)所能承受的壓力
- 壓力測試需要針對不同主題,所使用的數(shù)據(jù)和查詢也是真實用到的
- 基準(zhǔn)測試可能不關(guān)心業(yè)務(wù)邏輯,所使用的查詢和業(yè)務(wù)的真實性可以和業(yè)務(wù)環(huán)境沒關(guān)系
基準(zhǔn)測試的目的
- 建立MySQL服務(wù)器的性能基準(zhǔn)線
確定當(dāng)前MySQL服務(wù)器運行情況 - 模擬比當(dāng)前系統(tǒng)更高的負載,以找出系統(tǒng)的擴展瓶頸
增加數(shù)據(jù)庫并發(fā),觀察QPS,TPS變化,確定并發(fā)量與性能最優(yōu)的關(guān)系 - 測試不同的硬件、軟件和操作系統(tǒng)配置
- 證明新的硬件設(shè)備是否配置正確
如何進行基準(zhǔn)測試
對整合系統(tǒng)進行基準(zhǔn)測試
從整個系統(tǒng)進行基準(zhǔn)測試
從系統(tǒng)入口進行測試(如網(wǎng)站W(wǎng)eb前端,手機APP前端)
優(yōu)點:
- 能夠測試整個系統(tǒng)的性能,包括web服務(wù)器緩存、數(shù)據(jù)庫等
- 能反映出系統(tǒng)中各個組件接口間的性能問題體現(xiàn)真實性能狀況
缺點: - 測試設(shè)計復(fù)雜,消耗時間長
單獨對MySQL進行基準(zhǔn)測試
優(yōu)點:
- 測試設(shè)計簡單,所需耗費時間短
缺點: - 無法全面了解整個系統(tǒng)的性能基線
MySQL基準(zhǔn)測試的常見指標(biāo)
- 單位時間內(nèi)所處理的事務(wù)數(shù)(TPS)
- 單位時間內(nèi)所處理的查詢數(shù)(QPS)
- 響應(yīng)時間
平均響應(yīng)時間、最小響應(yīng)時間、最大響應(yīng)時間、各時間所占百分比 - 并發(fā)量:同時處理的查詢請求的數(shù)量
正在工作中的并發(fā)的操作數(shù)或同時工作的數(shù)量
基準(zhǔn)測試的步驟
計劃和設(shè)計基準(zhǔn)測試
- 對整個系統(tǒng)還是某一組件
- 使用什么樣的數(shù)據(jù)
- 準(zhǔn)備基準(zhǔn)測試及數(shù)據(jù)收集腳本
CPU使用率、IO、網(wǎng)絡(luò)流量、狀態(tài)與計數(shù)器信息等 - 運行基準(zhǔn)測試
- 保存及分析基準(zhǔn)測試結(jié)果
基準(zhǔn)測試中容易忽略的問題
- 使用生產(chǎn)環(huán)境數(shù)據(jù)時只使用了部分?jǐn)?shù)據(jù)
- 在多用戶場景中,只做單用戶的測試
- 在單服務(wù)器上測試分布式應(yīng)用
- 反復(fù)執(zhí)行同一查詢
推薦:使用相同架構(gòu)進行測試
容易緩存命中,無法反應(yīng)真實查詢性能
MySQL基準(zhǔn)測試工具之mysqlslap
下載及安裝
MySQL服務(wù)器自帶的基準(zhǔn)測試工具,隨MySQL一起安裝
特點:
- 可以模擬服務(wù)器負載,并輸出相關(guān)統(tǒng)計信息
- 可以指定也可以自動生成查詢語句
常用參數(shù)說明 - -auto-generate-sql 由系統(tǒng)自動生成SQL腳本進行測試
- -auto-generate-sql-add-autoincrement 在生成的表中增加自增ID
- -auto-generate-sql-load-type 指定測試中使用的查詢類型
- -auto-generate-sql-write-number 指定初始化數(shù)據(jù)時生成的數(shù)據(jù)量
- -concurrency 指定并發(fā)線程的數(shù)量
- -engine 指定要測試表的存儲引擎,可以用逗號分隔多個存儲引擎
- -no-drop 指定不清理測試數(shù)據(jù)
- -iterations 指定測試運行的次數(shù)
- -number-of-queries 指定每一個線程執(zhí)行的查詢數(shù)量
- -debug-info 指定輸出額外的內(nèi)存及CPU統(tǒng)計信息
- -number-int-cols 指定測試表中包含的INT類型列的數(shù)量
- -number-char-cols 指定測試表中包含的varchar類型的數(shù)量
- -create-schema 指定了用于執(zhí)行測試的數(shù)據(jù)庫的名字
- -query 用于指定自定義SQL的腳本
- -only-print 并不運行測試腳本,而是把生成的腳本打印出來
數(shù)據(jù)庫結(jié)構(gòu)優(yōu)化
良好的數(shù)據(jù)庫邏輯設(shè)計和物理設(shè)計是數(shù)據(jù)庫獲得高性能的基礎(chǔ)
數(shù)據(jù)庫結(jié)構(gòu)優(yōu)化的目的
- 減少數(shù)據(jù)冗余
- 盡量避免數(shù)據(jù)維護中出現(xiàn)更新,插入和刪除異常
- 插入異常:如果表中的某個實體隨著另一個實體而存在
- 更新異常:如果更改表中的某個實體的單獨屬性時,需要對多行進行更新
- 刪除異常:如果刪除表中的某一個實體則會導(dǎo)致其他實體的消失
- 節(jié)約數(shù)據(jù)存儲空間
- 提高查詢效率
數(shù)據(jù)庫結(jié)構(gòu)設(shè)計的步驟
需求分析:
- 全面了解產(chǎn)品設(shè)計的存儲需求
- 存儲需求
- 數(shù)據(jù)處理需求
- 數(shù)據(jù)的安全性和完整性
邏輯設(shè)計:
- 設(shè)計數(shù)據(jù)的邏輯存儲結(jié)構(gòu)
- 數(shù)據(jù)實體之間的邏輯關(guān)系,解決數(shù)據(jù)冗余和數(shù)據(jù)維護異常
物理設(shè)計:
- 根據(jù)所使用的數(shù)據(jù)庫特點進行表結(jié)構(gòu)設(shè)計
關(guān)系型數(shù)據(jù)庫:Oralce、SQLServer、Mysql、postgresSQL
非關(guān)系型數(shù)據(jù)庫:mongo、Redis、Hadoop
存儲引擎:Innodb
維護優(yōu)化:
- 根據(jù)實際情況對索引、存儲結(jié)構(gòu)等進行優(yōu)化
數(shù)據(jù)庫設(shè)計范式
設(shè)計出沒有數(shù)據(jù)冗余和數(shù)據(jù)維護異常的數(shù)據(jù)結(jié)構(gòu)
數(shù)據(jù)庫三范式
數(shù)據(jù)庫設(shè)計的第一范式
- 數(shù)據(jù)庫表中的所有字段都只具有單一屬性
- 單一屬性的列是由基本的數(shù)據(jù)類型所構(gòu)成的
- 設(shè)計出來的表都是簡單的二維表
數(shù)據(jù)庫設(shè)計的第二范式
要求一個表中只具有一個業(yè)務(wù)主鍵,也就是說符合第二范式的表中不能存在非主鍵列對只對部分主鍵的依賴關(guān)系
數(shù)據(jù)庫設(shè)計的第三范式
指每一個非 主屬性既不部分依賴于也不傳遞依賴于業(yè)務(wù)主鍵,也就是在第二范式的基礎(chǔ)上消除了非主屬性對主鍵的傳遞依賴
需求說明
按下面的需求設(shè)計一個電子商務(wù)網(wǎng)站的數(shù)據(jù)庫結(jié)構(gòu)
1、本網(wǎng)站只銷售圖書類商品
2、需要具有以下功能
用戶登陸 商品展示 供應(yīng)商管理 用戶管理 商品管理 在線銷售
需求分析及邏輯設(shè)計
用戶登陸及用戶管理功能
- 用戶必須注冊并登陸系統(tǒng)才能進行網(wǎng)上交易
用戶名來作為用戶信息的業(yè)務(wù)主鍵 - 同一時間一個用戶只能在一個地方登陸
- 用戶信息:{用戶名、密碼、手機號、姓名、注冊日期、在線狀態(tài)、出生日期}
只有一個業(yè)務(wù)主鍵,一定是符合第二范式
沒有屬性和業(yè)務(wù)主鍵存在傳遞依賴的關(guān)系,符合第三范式
商品展示及商品管理功能
- 商品信息:{商品名稱、分類名稱、出版社名稱、圖書價格、圖書描述、作者}
拆分- 商品信息:{商品名稱、出版社名稱、圖書價格、圖書描述、作者}
- 分類信息:{分類名稱、分類描述}
- 商品分類(對應(yīng)關(guān)系表):{商品名稱、分類名稱}
供應(yīng)商管理功能
- 供應(yīng)商信息:{出版社名稱、地址、電話、聯(lián)系人、銀行賬號}
在線銷售功能
- 在線銷售:{訂單編號、下單用戶名、下單日期、訂單金額、訂單商品分類、訂單商品名、訂單商品單價、訂單商品數(shù)量、支付金額、物流單號}
1、只有一個業(yè)務(wù)主鍵,負荷第二范式
2、訂單商品單價,訂單商品數(shù)量,訂單編號存在著傳遞依賴關(guān)系,不符合第三范式
3、數(shù)據(jù)冗余=》訂單商品信息和商品信息表中的數(shù)據(jù) - 訂單表:{訂單編號、下單用戶名、下單日期、支付金額、物流單號}
- 訂單商品關(guān)聯(lián)表:{訂單編號、訂單商品分類、訂單商品名、商品數(shù)量}
編寫SQL查詢出每一個用戶的訂單總金額
select 下單用戶名,sum(d.商品價格*b.商品數(shù)量)
from 訂單表 a join 訂單商品關(guān)聯(lián)表 b on a.訂單編號=b.訂單編號
join 商品分類關(guān)聯(lián)表 c on c.商品名稱=b.商品名稱 and c.分類名稱=b.訂單商品分類
join 商品信息表 d on d.商品名稱=c.商品名稱
group by 下單用戶名
假設(shè)下單用戶就是商品的收貨人,我們在發(fā)貨前一定要查詢出每個訂單的下單人的信息,而這些信息全部記錄在用戶信息表中
# 編寫SQL查詢出下單用戶和訂單詳情
完全符合范式化的設(shè)計有時并不能得到良好的SQL查詢性能。
反范式化設(shè)計
什么叫做反范式化設(shè)計
反范式化是針對范式化而言的,在前面介紹了數(shù)據(jù)庫設(shè)計的范式,所謂的反范式化就是為了性能和讀取效率的考慮而適當(dāng)?shù)膶?shù)據(jù)庫設(shè)計范式的要求進行違反,而允許存在少量的數(shù)據(jù)冗余,換句話來說反范式化就是使用空間來換取時間。
圖書在線銷售網(wǎng)站數(shù)據(jù)庫的反范式化改造
商品信息:{商品名稱,出版社名稱,圖書價格,圖書描述,作者}
分類信息:{分類名稱,分類描述}
商品分類關(guān)系:{商品名稱,分類名稱}
after
商品信息:{商品名稱,分類名稱,出版社名稱,圖書價格,圖書描述,作者}
分類信息:{分類名稱,分類描述}
銷售相關(guān)表
訂單表:{訂單編號,下單用戶名,下單日期,支付金額,物流單號}
訂單商品關(guān)聯(lián)表:{訂單編號,訂單商品分類,訂單商品名,商品數(shù)量}
after
訂單表:{訂單編號,下單用戶名,手機號,下單日期,支付金額,物流單號,訂單金額}
訂單商品關(guān)聯(lián)表:{訂單編號,訂單商品分類,訂單商品名,商品數(shù)量,商品單價}
反范式化改造后的查詢
**編寫SQL查詢出每一個用戶的訂單總金額
select 下單用戶名, sum(訂單金額)
from 訂單表
group by 下單用戶名;
**編寫SQL查詢出下單用戶和訂單詳情
select a.訂單編號, a.用戶名, a.手機號, b.商品名稱, b.商品單價, b.商品數(shù)量 from 訂單表 a join 訂單商品關(guān)聯(lián)表 b on a.訂單編號=b.訂單編號;
不能完全按照范式化的要求進行設(shè)計
考慮以后如何使用表
范式化設(shè)計的優(yōu)缺點
優(yōu)點:
- 可以盡量的減少數(shù)據(jù)冗余
數(shù)據(jù)表更新體積小 - 范式化的更新操作比反范式化更快
- 范式化的表通常比反范式化更小
缺點:
- 對于查詢小對多個表進行關(guān)聯(lián)
- 更難進行索引優(yōu)化
反范式化設(shè)計的優(yōu)缺點
優(yōu)點:
- 可以減少表的關(guān)聯(lián)
- 可以更好的進行索引優(yōu)化
缺點:
- 存在數(shù)據(jù)冗余及數(shù)據(jù)維護異常
- 對數(shù)據(jù)的修改需要更多的成本
物理設(shè)計
根據(jù)所選擇的關(guān)系型數(shù)據(jù)庫的特點對邏輯模型進行存儲結(jié)構(gòu)設(shè)計
物理設(shè)計設(shè)計的內(nèi)容
- 定義數(shù)據(jù)庫、表及字段的命名規(guī)范
- 選擇合適的存儲引擎
- 為表中的字段選擇合適的數(shù)據(jù)類型
- 建立數(shù)據(jù)庫結(jié)構(gòu)
定義數(shù)據(jù)庫、表及字段的命名規(guī)范
- 數(shù)據(jù)庫、表及字段的命名要遵守可讀性原則
- 數(shù)據(jù)庫、表及字段的命名要遵守表意性原則
- 數(shù)據(jù)庫、表及字段的命名要遵守長名原則
選擇合適的存儲引擎
存儲引擎 | 事務(wù) | 鎖粒度 | 主要應(yīng)用 | 忌用 |
---|---|---|---|---|
MyISAM | 不支持 | 支持并發(fā)插入的表級鎖 | SELECT, INSERT | 讀寫操作頻繁 |
MRG_MYISAM | 不支持 | 支持并發(fā)插入的表級鎖 | 分段歸檔,數(shù)據(jù)倉庫 | 全局查找過多的場景 |
Innodb | 支持 | 支持MVCC的行級鎖 | 事務(wù)處理 | 無 |
Archive | 不支持 | 行級鎖 | 日志記錄,只支持insert,select | 需要隨機讀取,更新,刪除 |
Ndb cluster | 支持 | 行級鎖 | 高可用性 | 大部分應(yīng)用 |
為表中的字段選擇合適的數(shù)據(jù)類型
當(dāng)一個列可以選擇多種數(shù)據(jù)類型時,應(yīng)該優(yōu)先考慮數(shù)字類型,其次是日期或二進制類型,最后是字符類型。對于相同級別的數(shù)據(jù)類型,應(yīng)該優(yōu)先選擇占用空間小的數(shù)據(jù)類型。
如何選擇正確的整數(shù)類型
|列類型|存儲空間|signed取值范圍|unsigned取值范圍|
|:--:|:--:|:--:|:--:|:--:|
|tinyint|1字節(jié)|-128127|0255|
|smallint|2字節(jié)|-3276832767|065535|
|mediumint|3字節(jié)|-83886088388607|016777215|
|int|4字節(jié)|-21474836482147483647|04294967295|
|bigint|8字節(jié)|。。。。|。。。。。|
如何選擇正確的實數(shù)類型
列類型 | 存儲空間 | 是否精確類型 |
---|---|---|
FLOAT | 4個字節(jié) | 否 |
DOUBLE | 8個字節(jié) | 否 |
DECIMAL | 每4個字節(jié)存9個數(shù)字,小數(shù)點占一個字節(jié) | 是 |
如何選擇VARCHAR和CHAR類型
VARCHAR類型的存儲特點
- varchar用于存儲變長字符串,只占用必要的存儲空間
- 列的最大長度小于255則只占用一個額外字節(jié)用于記錄字符串長度
- 列的最大長度大于255則要占用兩個額外字節(jié)用于記錄字符串長度
VARCHAR長度的選擇問題
- 使用最小的符合需求的長度
- varchar(5)和varchar(200)存儲'MySQL'字符串性能不同
VARCHAR的適用場景
- 字符串列的最大長度比平均長度大很多
- 字符串列很少被更新
- 使用了多字節(jié)字符集存儲字符串
CHAR類型的存儲特點
- CHAR類型是定長的
- 字符串存儲在CHAR類型的列中會刪除末尾的空格
- CHAR類型的最大寬度為255
CHAR類型的適用場景
- CHAR類型適合存儲所長度近似的值
- CHAR類型適合存儲短字符串
- CHAR類型適合存儲經(jīng)常更新的字符串列
如何存儲日期類型
DATATIME類型
以YYYY-MM-DD HH:MM:SS[.fraction] 格式存儲日期時間
datetime = YYYY-MM-DD HH:MM:SS
datetime(6) = YYYY-MM-DD HH:MM:SS.fraction
DATATIME類型與時區(qū)無關(guān),占用8個字節(jié)的存儲空間
時間范圍1000-01-01 00:00:00到9999-12-31 23:59:59
TIMESTAMP類型
存儲了由格林尼治時間1970年1月1日到當(dāng)前時間的秒數(shù)
以YYYY-MM-DD HH:MM:SS.[.fraction]的格式顯示,占4個字節(jié)
時間范圍1970-01-01 到2038-01-19
timestamp類型顯示依賴于指定的時區(qū)
在行的數(shù)據(jù)修改時可以自動修改timestamp列的值
date類型和time類型
1、使用date類型只需要3個字節(jié)
2、使用Date類型還可以利用日期時間函數(shù)進行日期之間的計算
date類型用于保存1000-01-01 到 9999-12-31之間的日期
time類型用于存儲時間數(shù)據(jù),格式為HH:MM:SS
存儲日期時間數(shù)據(jù)的注意事項
- 不要使用字符串類型來存儲日期時間數(shù)據(jù)
日期時間類型通常比字符串占用的存儲空間小
日期時間類型在進行查找過濾時可以利用日期來進行對比
日期時間類型還有著豐富的處理函數(shù),可以方便的對時期類型進行日期計算 - 使用Int存儲日期時間不如使用Timestamp類型