MYSQL數據庫學習系列四

                  MYSQL數據庫學習系列四

四.MYSQL的應用優化
4.1-MySQL索引優化與設計
什麼是索引
索引的意義 —— 快速定位要查找的數據
數據庫索引查找
全表掃描 VS 索引查找
如何根據首字母找到所在行
二分查找
B+tree
InnoDB表聚簇索引
索引中只放着排序字段和ID
創建索引
單列索引
create index idx_test1 on tb_student (name);
聯合索引
create index idx_test2 on tb_student (name, age);
索引中先根據name排序,name相同的情況下,根據age排序
索引維護
索引維護由數據庫自動完成
插入/修改/刪除每一個索引行都會變成一個內部封裝的事務
索引越多,事務越長,代價越高
索引越多對錶的插入和索引字段修改就越慢
控制表上索引的數量,切忌胡亂添加無用索引
如何使用索引
依據WHERE查詢條件建立索引
select a, b from tab_a where c=? ;
idx_c (c)select a, b from tab_a where c=? and d=?;
idx_cd (c, d)
排序order by, group by, distinct字段添加索引
select from tb_a order by a;select a, count() from tb_a group by a;
idx_a (a)
select from tb_a order by a, b;
idx_a_b (a, b)
select
from tb_a order where c=? by a;
idx_c_a (c, a)
索引與字段選擇性

某個字段其值的重複程度


選擇性很差的字段通常不適合創建單列索引

o男女比例相仿的列表中性別不適合創建單列索引
o如果男女比例極不平衡,要查詢的又是少數方(理工院校查女生)可以考慮使用索引

聯合索引中選擇性好的字段應該排在前面

select from tab_a where gender=? and name=?;
idx_a1 (name, gender)
聯合索引與前綴查詢
聯合索引能爲前綴單列,複列查詢提供幫助
idx_smp (a, b, c)where a=? ;where a=? and b=? ;where a=? and c=? ;(部分ok)
合理創建聯合索引,避免冗餘 (a) , (a, b) , (a, b, c) X (a, b, c) ok
長字段上的索引
在非常長的字段上建立索引影響性能
InnoDB索引單字段(utf8)只能取前767 bytes
對長字段處理的方法
oEmail類,建立前綴索引
Mail_addr varchar(2048)
idx_mailadd (Mail_addr(30)) ok
o住址類,拆分字段
Home_address varchar(2048)
idx_mailadd (Mail_addr(30)) ? -- 很可能前半段都是相同的省市區街道名稱
Province varchar(1024), City varchar(1024), District varchar(1024), Local_address varchar(1024) ... -- 建立聯合索引或單列索引
索引覆蓋掃
最核心SQL考慮索引覆蓋
select Name from tb_user where UserID=?
Key idx_uid_name(UserID, Name)

不需要回表獲取name字段,IO最小,效率最高
無法使用索引的情況
索引列進行數學運算或函數運算
where id+1=10; Xwhere id = (10-1); ok
year(col) < 2007; X
col < '2007-01-01'; ok

未含符合索引的前綴字段
Idxabc (a, b, c):where b=? and c=?; X
(b, c) ok

前綴通配,'
'和'%'通配符
Like '%xxx%'; XLike 'xxx%'; ok

where 條件使用NOT, <>, !=
字段類型匹配
o並不絕對,但是無法預測地會造成問題,不要使用
a int(11), idx_a (a)where a = '123'; Xwhere a = 123 ; ok
利用索引排序
idx_a_b (a, b)
能夠使用索引幫助排序的查詢:
order by a
a = 3 order by border by a, border by a desc, b desc
a > 5 order by a
不能使用索引幫助排序的查詢:
order by b
a > 5 order by b
a in (1, 3) order by border by a asc, b desc
如何確定一個查詢走沒走索引,走了哪個索引
explain是確定一個查詢如何走索引最簡便有效的方法 explain select
from tb_test ;
關注的項目
otype:查詢access的方式
okey:本次查詢最終選擇使用哪個索引,NULL爲未使用索引
okey_len:選擇的索引使用的前綴長度或者整個長度
orows:可以理解爲查詢邏輯讀,需要掃描過的記錄行數
oextra:額外信息,主要指的fetch data的具體方式
4.2-MySQL數據庫設計
什麼是Schema設計
設計數據庫的表,索引,以及表和表的關係
o在數據模型的基礎上將關係模型轉化爲數據庫表
o滿足業務模型需要基礎上根據數據庫和應用特點優化表結構
爲什麼Schema需要設計
Schema關係到應用程序功能與性能
o滿足業務功能需要
o同性能密切相關
o數據庫擴展性
o滿足周邊需求(統計,遷移等)
關係型數據庫修改Schema經常是高危操作
oSchema設計要體現一定的前瞻性
完全由開發者主導的Schema設計
着眼於實現當前功能
完全基於功能的設計可能存在一些隱患
o不合理的表結構或索引設計造成性能問題
o沒有合理評估到數據量的增長造成空間緊張而且難以維護
o需求頻繁修改造成表結構經常變更
o業務重大調整導致數據經常需要重構訂正
基於性能的表設計
根據查詢需要設計好索引
根據核心查詢需求,適當調整表結構
基於一些特殊業務需求,調整實現方式
索引
正確使用索引
更新儘可能使用主鍵或唯一索引
主鍵儘可能使用自增ID字段
核心查詢覆蓋掃描
o用戶登錄需要根據用戶名返回密碼用於驗證create index idx_uname_passwd on tb_user (username, password);
o建立聯合索引避免回表取數據
反範式,冗餘必要字段
針對核心SQL保留查詢結果所必須的冗餘字段,避免頻繁join
o例:消息表中冗餘了每次讀消息必須返回的nickname字段,避免每次讀消息都變成join操作。代價是用戶修改nickname成本變高。
拆分大字段
拆分大字段到單獨表中,避免範圍掃描代價大
o例:博文表拆分兩份,標題表只保留標題和內容縮略部分,用於快速批量返回標題列表,正文表保存大段博文內容,用於點開文章單個讀取
避免過多字段或過長行
根據SQL必要返回設計字段,有必要就拆表,避免過多字段
一次沒有必要獲取那麼多列數據
行過長導致表數據頁記錄變少,範圍掃描性能降低
更新數據也代價增加
16K也最少放2行,可能出現行遷移
分頁查詢
避免limit + offset過大
應該使用自增主鍵ID模擬分頁
o第一頁,直接查
o得到第一頁的max(id)=123(一般是最後一條記錄)
o第二頁,帶上id>123查詢:where id>123 limit 100
o這樣每次只需要掃描100條數據
要求業務上禁止查詢XX頁之後的數據
熱點讀數據特殊處理
根據數據獲取的頻率或數量不同對熱點數據做特殊處理
o例1:論壇系統中置頂帖、公告貼,可以單獨拆分存儲,由於每次訪問都要全部讀出來,單獨放在一起,避免每次都到普通表中隨機找出來
熱點寫數據特殊處理
根據數據獲取的頻率或數量不同對熱點數據做特殊處理
o例2:微博系統中對於大量關注的熱點賬號消息從"推"改爲"拉",避免過量insert操作。
準實時統計
對不需要精確結果的計數等統計要求,建立定期更新結果表
o例:首頁要求展示動態成交總金額,維護一個計數表,每分鐘根據原表註冊時間獲取增量sum值更新計數表,避免每次用戶刷新都要掃描交易全記錄表
實時統計改進1 - 觸發器實時統計
對需要精確統計的計數利用數據庫觸發器維護計數表
o例:用戶量衝億活動要求實時統計,用戶表上加觸發器,每次有新用戶插入就同時在計數表+1
實時統計改進2 - 緩存實時統計
對需要精確統計的計數利用前端緩存實時維護計數
o例:用戶量衝億活動要求實時統計,註冊數量在緩存中實時維護,每註冊一個就+1,完全避免數據庫讀寫操作。緩存萬一故障失效,可從數據庫整體count重新獲取。
實時統計改進2 - 最大自增ID獲取總數
很多邏輯可以利用自增ID主鍵最大值直接作爲總數
o例:用戶量衝億活動要求實時統計,用戶表加上自增ID作爲主鍵,只要取當時max(ID)就可以得到用戶總數
課拓展性設計
可拓展性
o硬件資源增長有極限的情況下處理儘可能久的線上業務
數據分級,冷數據歸檔與淘汰
o可以不斷釋放空間供新數據使用
爲數據分佈式做準備
o分庫分表
o水平拆分
o犧牲一定的關係模型支持
分區表與數據淘汰
range分區
適合數據需要定期過期的大表
單個分區掃描遷移數據到歷史庫避免全表掃描IO開銷
刪除單個分區非常高效
分區表與垂直分區
list分區
適合將來可能要基於地區,類目等方式垂直拆分數據的方式
清理節點上不要的數據非常高效
分區表與水平分區
hash分區
適合將來需要做水平拆分的表
清理節點上不要的數據非常高效
MySQL分區表的侷限
主鍵或唯一鍵必須包含在分區字段內
分區字段必須是整數類型,或者加上返回整數的函數
滿足周邊需求
爲周邊需求額外增加表設計
o爲後臺統計任務增加特殊索引
o爲數據遷移或統計需求增加時間戳
統計和後臺需求
統計運行SQL往往和線上有很大不同
o利用MySQL——主多從,主從可以建不同索引的特性將統計分流到特定從庫
o包括一些特殊用戶批量查詢等,所有對線上有IO壓力的查詢都要讀寫分離
自動更新時間戳
統計需求經常要求從線上讀走增量數據
表的第一個timestamp類型字段再寫入時如果不填值,會自動寫入系統時間戳
表的第一個timestamp類型字段每次記錄發生更新後都會自動更新
在update_time字段上建索引用於定時導出增量數據
Schema設計與前瞻性
基於歷史經驗教訓,預防和解決同類問題
把折騰DBA夠嗆的所有Schema改造的原因記錄並分析總結 例:
業務爲例用戶信息加密做了大改造
o數據庫結果大量改動,增加了加密字段,驗證策略表,所有表重新訂正數據等等
o是否所有用到用戶信息管理的應用都要去上線就用密文?
程序bug誤刪數據,線上風險大
o改造業務流程,不再刪除數據,加入is_deleted標記位,經常給各種表加
o今後的類似表是否一上線就都用標記位的方式,並加上修改原因字段?
支付類應用後期做了風控改造
o對線上訂單大表改造,加了限額,終端類型等字段
o遇到支付類應用,是否一上線就提示業務是否需要考慮風控並留好相關字段?
4.3-MySQL容量評估
性能容量評估
分析線上業務場景
評估數據庫服務器所需性能指標
預估可能成爲瓶頸的服務器資源
幫助數據庫性能調優
數據庫服務器硬件性能指標
磁盤IO性能
內存容量
CPU
網絡吞吐量
磁盤容量
數據庫業務特點關鍵詞
OLTP/OLAP類型
併發請求
讀寫比例
數據量
冷熱數據比
數據分級存儲
OLTP/OLAP
T = Transaction
面向廣大用戶,高併發,較短事務操作
互聯網應用絕大部分屬於OLTP
OLTP看重服務器CPU,內存,寫事務較多或內存不夠則依賴磁盤IO
A = Analytical
通常面向內部人員,大規模複查詢
OLAP看重磁盤掃描的IO能力,部分依賴內存排序
併發請求 - 衡量線上業務繁忙程度
業務高峯時數據庫的每秒併發訪問量是多少
通過應用服務器數量,連接池配置判斷
通過產品估算初上線用戶規模和用戶增長速度判斷
通過實際業務業務類型判斷
併發量相關資源:CPU
讀寫比例 - 描述應用程序如何使用數據庫
線上業務select只讀與update/delete/insert寫操作比例
delete/update通常都是先讀再寫
insert需要區分數據寫入時持續insert還是大量導入數據
根據業務實際場景分析
多讀場景相關資源:內存
多寫場景相關資源:磁盤IO
數據量 - 總量
數據庫服務器存儲設備可擴容能力的上限
根據估算的業務量,寫入模式,分析數據增長量
預估一個硬件升級週期內數據庫可存放數據的總量,上線時要留好餘量
數據總量相關資源:磁盤容量
冷數據與熱數據 - 有用數據的實時集合
熱數據,線上最新一定週期內將被反覆訪問的數據
冷數據,線上保存着的,最近不會被在線用戶用到的數據
估算活躍用戶量,數據增長量等預估熱數據量
內存大小儘可能足夠存放線上實時熱數據
熱數據相關資源:內存
線上數據分層存儲 - 緩解線上磁盤空間壓力
最新熱數據確保放在內存中
還可能訪問到的較早數據存放在線上庫磁盤中
更早的不會常規訪問的數據定期遷移至歷史庫中
區分哪些數據時效性強可以遷移
服務器資源選型 - 將可選方案列出來
資源指標 可選方案
磁盤IO性能 單盤 -> 盤陣; SATA -> SAS; HDD -> SSD
內存容量 較小內存 -> 較大內存
CPU 普通 -> 多核,超線程
網絡吞吐量 千兆 -> 萬兆; 單網卡 -> 多路;
磁盤容量 單盤 -> 盤陣; 單盤 -> LVM
案例一,網易雲音樂曲庫數據庫服務器評估
用於存放線上數千萬歌曲信息
確定屬於OLTP線上類型數據庫
併發請求量
o50臺應用服務器,每臺最大連接數100
o可能峯值5000qps,併發請求量較大
CPU需求高
讀寫比例
o訪問模式以用戶列出歌單和播放歌曲時查詢歌曲信息爲主,用戶只有只讀查詢
o寫數據發生在錄入新歌或修改歌曲信息時後臺操作,寫比例小,且爲批量導入
o讀寫比100:1
數據總量
o估算每首歌信息8K,總計5000萬,總量400G
o數據總量增長相對緩慢
冷熱數據
o5000萬歌曲中大約40%可能被訪問,10%屬於熱點歌曲
o熱數據大約<=40G
數據分級存儲需求
o由於沒有用戶產生的數據,歌曲信息無法分級存儲
內存需求一般,>=40G
磁盤IO能力需求一般
網絡流量要求,8k*2500/1024 ≈ 20MB/S,一般
資源指標 可選方案
磁盤IO性能 兩塊SAS做RAID1
內存容量 96G內存
CPU 2c8core超線程 相當於32核
網絡吞吐量 千兆雙網卡bunding
磁盤容量 900G
案例二,網易理財銷售數據庫服務器評估
用於存放理財用戶線上訂單
確定屬於OLTP線上類型數據庫
業務場景有明顯特徵
o特定高息產品秒殺銷售時間窗有大量併發訂單寫入
o平時只有少量訂單查詢和請求,和較低的常規產品購買請求
評估應以滿足最關鍵的業務高峯爲基準
併發請求量
o秒殺期間持續時間短,但是併發量預估30臺應用服務器約2000tps
讀寫比例
o高峯時寫訂單是主要開銷操作
CPU要求高
磁盤IO要求很高
數據總量
o根據業務分析,訂單屬於寫入瞬時量大,總量較小,單筆金額較高
o總量預估一年成交百萬級別,增長較穩定
o判斷數據存儲需求小於200G
冷熱數據
o峯值寫入爲主,內存要求存放熱點期間產生的髒數據即可
數據分級存儲需求
o用戶訂單業務約定頁面展示最近半年訂單,半年前的需要到歷史查詢頁面專門查詢
o因此可以做分級存儲,遷移所有半年前的訂單至歷史庫
內存需求一般, >= 30G
磁盤空間需求一般, >=200G
磁盤IO能力需求很高
網絡要求較高
o併發流量較高
o響應速度要求高
資源指標 可選方案
磁盤IO性能 兩塊SSD做RAID1
內存容量 64G內存
CPU 2c8core超線程 相當於32核
網絡吞吐量 萬兆雙網卡bunding
磁盤容量 600G
4.4-MySQL性能測試
爲什麼需要性能測試
對線上產品缺乏心理預估
重現線上異常
規劃未來的業務增長
測試不同硬件軟件配置
性能測試的分類
設備層的測試
業務層的測試
數據庫層的測試
設備層的測試
關注的指標
o服務器、磁盤性能
o磁盤壞塊率
o服務器壽命
業務層測試
針對業務進行測試
數據庫層測試
什麼情況下要做MySQL的測試
o測試不同的MySQL分支版本
o測試不同的MySQL版本
o測試不同的MySQL參數搭配
MySQL測試分類
CPU Bound
IO Bound
寫入測試 更新測試 純讀測試 混合模式
常用的測試工具
開源的MySQL性能測試工具
osysbench
otpcc-mysql
omysqlslap
針對業務編寫性能測試工具
oblogbench
性能測試衡量指標
服務吞吐量(TPS, QPS)
服務響應時間
服務併發性
Sysbench
業界較爲出名的性能測試工具
可以測試磁盤、CPU、數據庫
支持多種數據庫:Oracle, DB2, MySQL
需要自己下載編譯安裝
建議版本:sysbench0.5
編譯安裝Sysbench
下載sysbench
ogit clone https://github.com/akopytov/sysbench.git
編譯&安裝
o./autogen.sh
o./configure
omake && make install
Sysbench流程
常見的做法
初始化數據 -> 運行測試 -> 清理數據
Prepare語法
sysbench --test=parallel_prepare.lua --oltp_tables_count=1 --rand-init=on --oltp-table-size=500000000 --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=sys --mysql-password=netease --mysql-db=sbtest --max-requests=0 prepare
參數 含義
--test=parallel_prepare.lua 運行導數據的腳本
--oltp_tables_count 測試需要幾張表
--oltp-table-size 每張表的大小
--mysql-host MySQL Host
--mysql-port MySQL Port
--mysql-db MySQL DB
--mysql-user MySQL User
--mysql-password MySQL Password
--rand-init 是否隨機初始化數據
--max-requests 執行多少個請求之後停止
prepare 執行導數據
Sysbench表結構
create table 'sbtest1'(
'id' int(10) unsigned not null AUTO_INCREMENT,
'k' int(10) unsigned not null DEFAULT '0',
'c' char(120) not null DEFAULT '',
'pad' char(60) not null DEFAULT '',
PRIMARY KEY ('id'),
KEY 'k_1' ('k')
) ENGINE=InnoDB AUTO_INCREMENT=3000000001 DEFAULT CHARSET=utf8 MAX_ROWS=1000000
Run語法
sysbench --test=oltp.lua --oltp_tables_count=1 --num-threads=100 --oltp-table-size=500000000 --oltp-read-only=off --report-interval=10 --rand-type=uniform --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=sys --mysql-password=netease --mysql-db=sbtest --max-time=1000 --max-requests=0 run
參數 含義
--test=oltp.lua 需要運行的lua腳本
--oltp_tables_count 測試需要幾張表
--oltp-table-size 每張表的大小
--num-threads 測試併發線程數
--oltp-read-only 是否爲只讀測試
--report-interval 結果輸出間隔
--rand-type 數據分佈模式,熱點數據或者隨機數據
--max-time 最大運行時間
--max-requests 執行多少個請求之後停止
prepare 開始測試
特殊情況
寫入測試
寫入數據進行測試 -> 清理數據
cleanup
手動drop掉表和database
使用sysbench提供的cleanup命令
sysbench --test=parallel_prepare.lua --oltp_tables_count=1 --rand-init=on --oltp-table-size=500000000 --mysql-host=127.0.0.1 --mysql-port=3306 --mysql-user=sys --mysql-password=netease --mysql-db=sbtest --max-requests=0 cleanup
Tpcc-mysql

TPC-C是專門針對聯機交易處理系統(OLTP系統)的規範


Tpcc-mysql由percona根據規範實現


下載Tpcc-mysql

obzr branch lp:~percona-dev/perconatools/tpcc-mysql

編譯安裝

使用Tpcc-mysql的步驟
創建表結構和索引 -> 導數據 -> 運行測試 -> 數據清理
創建表結構
create_table.sql
add_fkey_idx.sql
Tpcc-load
tpcc_load [server] [DB] [user] [pass] [warehouse]
函數 含義
server 數據庫IP
DB DB名稱
user 用戶名
pass 密碼
warehouse 倉庫數量
Tpcc-start
tpcc_start -h server_host -P port -d database_name -u mysql_user -p mysql_password -w warehouse -c connections -r warmup_time -I running_time -i report-interval -f report-file
函數 含義
warehouse 倉庫數量
connections 併發線程數
warmup_time 預熱時間
running_time 運行時間
report_interval 輸出時間間隔
report_file 輸出文件
總結
IO Bound測試數據量要遠大於內存、CPU Bound測試數據量要小於內存
測試時間建議大於60分鐘,減小誤差
Sysbench更傾向於測試MySQL性能、TPCC更接近於業務
運行測試程序需要同時監控機器負載,MySQL各項監控指標

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章