【MySQL】MySQL开发注意事项与SQL性能优化步骤
MySQL簡介
地表最流行數據庫
名副其實
什么是MySQL?
- 世界上應用最廣泛且靈活的開源關系數據庫
MySQL 是應用最廣泛的開源關系數據庫,是許多常見網站,應用程序和商業產品使用的主要關系數據存儲,MySQL 有20多年的社區開發和支持歷史,是一種可靠,穩定而安全的基于SQL的數據庫管理系統,MySQL數據庫適用于各種使用案例,包括任務關鍵型應用程序,動態網站以及用于軟件,硬件和設備的嵌入式數據庫
MySQL特點
- 易安裝:支持rpm等包安裝,支持解壓安裝,支持編譯安裝,docker部署
- 易擴展:開源特性,插件式存儲引擎,靈活的高可用架構
- 易使用:標準SQL,豐富工具
- 高性能:基于硬件支撐,基于架構設計
MySQL資源
MySQL文檔
MySQL架構
- 接入層:外部接口
- 服務層:數據庫功能實現層
- 引擎層:數據存取的具體實現
- 存儲層:物理存儲
MySQL概念—存儲引擎
MySQL 中的數據用各種不同的技術存儲在文件(或者內存)中,這些技術中的每一種技術都使用不同的存儲機制,索引技巧,鎖定水平并且最終提供廣泛的不同功能和能力,通過選擇不同的技術,能夠獲得額外的速度或者功能,從而改善應用的整體功能
MySQL概念—數據庫,模式,用戶
數據庫和模式是同一個概念,是若干個數據庫對象的集合
用戶用于實現訪問數據庫的權限認證
MySQL概念—數據庫,用戶,存儲引擎關系
單個用戶可以連接多個數據庫
一個數據庫對應單個存儲引擎
MySQL安裝—rpm安裝
MySQL安裝—解壓安裝
MySQL安裝—編譯安裝
MySQL安裝—docker部署
MySQL安裝—四種安裝對比
| rpm安裝 | 外網或repo源或rpm包 | 簡單 | 短 | 差 | 單機單庫 | 開發測試 |
| 解壓安裝 | 外網或二進制包 | 略難 | 短 | 高 | 單機多庫 | 線上部署 |
| 編譯安裝 | 外網或源碼包 | 較難 | 長 | 高 | 單機多庫 | 學習 |
| docker部署 | 外網或docker倉庫 | 簡單 | 短 | 高 | 單機多庫 | 開發測試 |
MySQL架構
MySQL架構 — 系統架構
MySQL架構 — 文件,進程,內存
MySQL架構 — 文件管理
MySQL架構 — 日志系統
- 錯誤日志(error)
- MySQL服務實例啟動,運行或者停止等相關信息
- 普通查詢日志(general)
- MySQL服務實例運行的所有SQL語句或者MySQL命令
- 二進制日志(binary)
- 對數據庫執行的所有更新語句,不包括 select 和 show 語句
- 慢查詢日志(slow)
- 執行時間超過 long_query_time 設置值的SQL語句,或者沒有使用索引的SQL語句
- 重做日志(redo)
- 記錄了事務修改后的內容,以便實例crash時可以恢復事務
- 回滾日志(undo)
- 記錄事務修改前的內容,以便事務回滾時可以將數據恢復到事務開始前
MySQL架構 — 日志系統_binlog
- binlog內容
- 記錄MySQL數據庫的所有更新操作,但不記錄對數據庫的查詢select或show等(這些可以被general日志記錄)
- binlog用途
- 主從復制
- 增量備份恢復
- binlog模式
- statement:記錄sql語句(一個sql只記錄一次)
- row:記錄每一行修改記錄(一個sql影響多行會產生多條記錄)
- mix:根據
- binlog查看
- 自帶工具mysqlbinlog查看
binlog示例
MySQL架構 — 日志系統_redo/undo
MySQL復制技術 — 基本原理
MySQL復制技術 — 復制技術發展
- 事務丟失問題
主庫宕機時,主庫上已提交的事務未發送到從庫。 - 半同步改進
確保至少一個從庫收到 binlog。 - 數據不一致問題
從庫收到binlog并生成binglog后主庫確認提交,若此時從庫sql進程還未將數據寫入,查詢或主從切換存在主從不一致。 - 超時退化為異步
復制從庫接收應答超時后,主從復制退化為異步復制 - 增強半同步改進
至少一個從庫完成寫庫后返回提交確認,主庫才確認完成commit - 若環境主庫性能下降
弱網環境等待從庫應答會降低主庫性能 - 組復制要求
至少3節點的集群。 - 原理
基于paxos協議進行廣播通知所有主節點,攜帶全局事務號確保所有節點接受事務的順序一致性。可容忍失敗節點:(n-1)/2
MySQL復制技術 — 復制技術對比
| 組復制 | 對性能要求高,追求高吞吐,低延遲的場景 | 數據一致性好 | 性能低,吞吐量降低,TP999上升 |
| 異步復制 | 對數據一致性要求高 | 性能高 | 數據不一致問題比較嚴重 |
| 半同步復制 | 對數據一致性要求高 | 性能中 | 數據不一致問題比異步復制好一點,但是有時候會退化為異步復制 |
| 增強半同步復制 | 對數據一致性要求高,無法忍受數據不一致的問題 | 性能中 | 數據不一致問題比半同步復制好一些,但是有時候會退化為異步復制 |
MySQL高可用架構
MySQL工具
MySQL工具—開發工具—HeidiSQL
MySQL工具—開發工具—SQLyog
MySQL工具—開發工具—Workbench
MySQL工具—備份恢復
文本導出
select * from Table into outfile '/路徑/文件名' fields terminated by ',' enclosed by '"' lines terminated by '\r\n';文本導入
LOAD DATA INFILE /路徑/文件名' INTO TABLE Table FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'LINES TERMINATED BY '\r\n';邏輯備份
mysqldump --master-data=2 --flush-logs --single-transaction --databases db1 db2 --user=<xxx> --password=<xxxx> --port=<3306> --host=<10.0.0.1> > backup_fulldb.sql;邏輯恢復
mysql --user=<xxx> --password=<xxxx> --port=<3306> --host=<10.0.0.1> < backup_fulldb.sql;MySQL工具—備份恢復—工具對比
| 導出 | mysql命令之select into outfile | 文本導出 | 純文本 | ||
| 導入 | mysql命令之load data infile | 文本導入 | 純文本 | ||
| 備份 | mysqldump | 少量數據備份 | 邏輯備份,單線程 | ||
| 備份/恢復 | xtrabackup | 大量數據備份,快速主從搭建 | 物理備份,多線程 | ||
| 備份 | mydumper | 邏輯備份,多線程 | |||
| 恢復 | mysqlloader | 邏輯備份,多線程 |
MySQL開發
MySQL開發—數據庫對象—與Oracle的異同
MySQL數據結構----數據類型
MySQL數據結構----數據類型—數值
MySQL數據結構----數據類型—字符
MySQL數據結構----數據類型—二進制
MySQL數據結構----數據類型—時間
MySQL開發—字符集—相關參數
MySQL開發—字符集—主要分類
MySQL開發—索引結構
- 主鍵
btree+索引結構:葉子結點包含完整的行數據 - 二級索引
btree+索引結構:葉子結點包含主鍵的指針和二級索引字段值
MySQL開發—索引結構–主鍵與非主鍵
- 主鍵查詢無需回表
- 非主鍵查詢需要回表
MySQL開發—設計參考—合適的數據類型
- 數值
建議整數使用 int,小數使用 decimal - 字符類型
不建議使用枚舉,集合類型,大對象,建議使用varchar2 - 二進制
不建議使用大對象存儲圖音視,大文本 - 日期
- 區別一:時區支持:timestamp支持時區。datetime不支持時區
- 區別二:數據范圍:timestamp有效數據范圍為1970 ~ 2038,datetime為0001 ~ 9999
- 建議:建議使用datetime
MySQL開發—設計參考—主鍵的選擇
- 自增序列情況下增加650:直接在主鍵樹的最右側添加
- 非自增序列情況下增加350:需要在300和400之間插入,要移動前后葉子結點,若相關頁存放已滿,還需要分裂塊
建議:使用自增序列,默認使用int,超過40億使用bigint
MySQL開發—設計參考—索引選擇
- 如何選擇索引字段
- where,on中經常出現的
- 和其他表有關聯的
- group by,order by 中出現的
- 非空字段
- 排列聯合索引字段
- 高頻出現的字段放最前面
- 重復率低的字段放最前面
- 影響索引使用
- 對索引列計算
- 字段可為空
- 避免使用不確定查詢(or,not/not in,<>,like)
MySQL開發—設計參考—字符集
character set: utf8mb4 collate:utf8mb4_0900_ai_ci utf8mb4_unicode ci utf8mb4_general ci字符集設置
- db級全局設置最佳
- 表級設置次選
- 避免字段級設置
字符集選擇
- utf8mb4
MySQL優化
MySQL優化—執行計劃—查看方式
MySQL優化—執行計劃—查看特定SQL
查看特定sql
explain
查看特定連接的sql執行計劃
explain for connection <線程id>
MySQL優化—執行計劃—閱讀方式
閱讀方法
- 不同的id由大往小讀
- 相同的id由上往下讀
示例:
- 先訪問 id = 1 的t1表,返回結果集給上一層id=1
- id=1的有兩條記錄
- 先訪問id=1且table=<derived2>(注:此處為子查詢s1),返回結果集給下一個id=1的其他記錄
- 在訪問id=1 且table=t2的表,進行關聯匹配
偽代碼
loop s1<derived2> for (select max(id) as id form t1):loop t2 for (select * from t2):if t2.id = s1.id thenreturn t2;elsenext;end if;end loop; end loop;MySQL優化—執行計劃—屬性簡介
- id:查詢序號
- select_type:查詢方式
- table:所使用的表名稱
– <unionM,N>:該行是id為M和N的行的并集
– <derivedN>:該行是id為N的行的派生表
– <subqueryN>:該行是物化子查詢的結果 - partitions:使用的分區信息,NULL表示該表不是分區表
- type:連接類型
- possible_keys:可能使用的索引,如果此列是NULL,則沒有相關的索引,建議檢查 WHERE字句,以確定是否適合創建索引或調整where條件
- key:MySQL實際使用的索引。在大多數情況下,key中的值都在possible_key里面
- key_len:顯示索引使用的字節數,key_len顯示的值為索引字段的最大長度,并非實際使用 長度,越短越好
- ref:ref列顯示哪些列或者常量與key中的索引進行比較,以從表中選擇行
- rows:MySQL查詢需要遍歷的行數。
- filtered:被條件過濾的行數百分比。最大值為100,表示沒有行過濾,值從100減小表示過濾 增加。rows表示檢查的行數,rows * filtered/100表示過濾后的行數,也就是與下表進行連 接的行
- Extra:執行計劃的額外信息
MySQL優化—執行計劃—select-type
示例
簡單查詢
子查詢
關聯查詢
MySQL優化—執行計劃—type(連接類型)
連接優先級:System --> const --> eq_ref --> ref --> fulltext --> ref_or_unll --> index_merge --> unique_subquery --> index_subquery --> range --> index --> ALL
- system : 該表只有一行,這是const連接的特殊情況。(單行常量表)
- const:該表最多只有一個匹配行,該行在查詢開始時讀取。因為只有一行,所以優化器的其余部分可以將這一行中的值 做為常量,因為它值讀取一次。const在基于主鍵或者唯一性索引比較時使用。(主鍵/唯一索引的等值查詢)
- eq_ref:與驅動表的連接查詢,后表(被驅動表)僅讀取一行數據,當被驅動表存在主鍵索引或者unique+not null時使用, eq_ref用于使用"="運算的索引列。(主鍵/唯一索引的關聯查詢)
- ref:與驅動表的連接查詢,后表(被驅動表)讀取一行或多行數據。ref用于僅使用key的最左前綴,或者說key不是 PAIMARY KAY或UNIQUE索引。換句話說,如果連接無法根據KEY選擇單個行,則使用ref,否則使用eq_ref。ref可以 用于使用"=“或者”<=>"運算符進行的比較。(左側索引/普通索引的等值查詢)
- fulltext:使用FULLTEXT進行連接
- ref_or_null:這種方式類似于ref,但是MySQL會額外搜索包含NULL值的行
- index_merge:索引合并優化,把多個索引合并為一個使用
- unique_subquery:該類型替換eq_ref形式下的IN子查詢,子查詢中最多返回一個值,提高查詢效率
- index_subquery:該類型類似于unique_subquery,它用來替代子查詢,子查詢中返回值的個數不確
- range:使用索引去檢索一個范圍的行數據,key列是使用到的索引,ref列為NULL。range可以在=,<>,>,>=,<,<=,IS NULL,<=>,BETWEEN,LIKE或IN() (索引范圍掃描)
- index:index與ALL相似,只是索引樹被掃描(全索引掃描)
- ALL:全表掃描,如果驅動表不是以const方式獲取數據的,則可以會導致非常糟糕的查詢性能。通常可以添加索引來避 免權標掃描(全表掃描)
MySQL優化—優化方法
- 理清業務邏輯
- 讀懂執行計劃
- 簡化SQL
- 逐步優化
總結
以上是生活随笔為你收集整理的【MySQL】MySQL开发注意事项与SQL性能优化步骤的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【多线程】线程池拒绝策略详解与自定义拒绝
- 下一篇: 【MYSQL】分组之后获取每组最新的数据