數據表引擎
innodb 引擎
默認事務型引擎,最重要最廣泛的存儲引擎,性能非常優秀
數據存儲在共享表空間,可通過配置分開
對主鍵查詢的性能高於其他類型的存儲引擎
內部做了很多優化,從磁盤讀取數據時自動在內存構建hash 索引,插入數據時自動構建插入緩衝區
通過一些機制和工具支持真正的熱備份
支持崩潰後的安全恢復
支持行級鎖
支持外鍵
MyISAM 引擎
5.1 版本前是默認引擎
擁有全文索引、壓縮、空間函數
不支持事務和行級鎖,不支持奔潰後安全恢復
表存儲在兩個文件,MYD 和MYI
設計簡單,某些場景下性能很好
其他引擎:
Archive、Blackhole、CSV、Memory
MySQL 鎖機制
當多個查詢同一時刻進行數據修改時,會產生併發控制的問題
- 共享鎖(讀鎖)
- 排他鎖(寫鎖)
鎖粒度
- 表鎖
系統性能開銷最小,會鎖定整張表,myisam 使用表鎖 - 行鎖
最大程度的支持併發處理,但是也帶來了最大的鎖開銷,innodb 實現行級鎖
char 與varchar
char 是定長的,根據定義的字符串長度分配足量空間char 會根據需要採用空格進行填充以方便比較char 適合存儲很短的字符串,或者所有值都接近同一個長度char 長度超過設定的長度,會被截斷
varchar 用於存儲可變長字符串,比定長類型更加節省空間
varchar 使用1 或2 個額外字節記錄字符串的長度,列長度小於255 字節用1 個字節表示,否則用2個
varchar 長度超過設定的長度,會被截斷
比較
對於經常變更的數據,char 比varchar 更好,char 不容易產生碎片
對於非常短的列,char 比varchar 在存儲空間上更有效率
只分配真正需要的空間,更長的列會消耗更多的內存
索引
- 大大減少服務器需要掃描的數據量
- 幫助服務器避免排序和臨時表
- 將隨機I/O 變順序I/O
- 大大提高查詢速度,降低寫的速度,佔用磁盤空間
索引類型
- 普通索引
- 主鍵索引
- 唯一索引
- 組合索引
- 外鍵索引
- 全文索引
索引創建原則
- 最適合索引的列是出現在where 子句的列,或連接子句中的列,而不是出現在select 的關鍵字後的
列 - 索引列的基數越大,索引效果越好
- 對字符串進行索引,應指定一個前綴長度,可以節省大量的索引空間
- 根據情況創建複合索引,複合索引可以提高查詢效率
- 避免創建過多索引,索引會額外佔用磁盤空間,減低寫操作效率
- 主鍵儘可能選擇較短的數據類型,可以有效減少索引的磁盤佔用,提高效率
索引的注意事項
- 複合索引遵循前綴原則
- like 查詢,%不能在前,可以使用全文索引
- column is null 可以使用索引
- 如果MySQL 估計使用索引比全表掃描更慢,會放棄使用索引
mysql 優化
查詢速度慢的原因
- 打開慢查詢日誌,通過pt-query-dugest 分析
- show profile,通過set profiling=1;開啓,服務器上執行的所有語句消耗時間都會記錄到臨時表。
show profile for query QUERY_ID 查詢指定查詢 - show status,查詢一些計數器,猜出哪些代價高或消耗時間多
- show processlist,查詢線程狀態進行分析
- explain,分析單個SQL 語句查詢
優化查詢過程中的數據訪問
- 訪問數據太多導致性能下降
- 確定應用程序是否檢索大量超過需要的數據,可能是太多列或者行
- 確定mysql 是否分析大量不必要的數據行
- 查詢不需要的記錄,使用limit 限制
- 奪標關聯返回全部列指定A.id,A.name
- 總數取出全部列,select * 會讓優化器無法完成所有覆蓋掃碼的優化
- 重複查詢相同的數據,可以緩存數據
- 改變數據庫和表的結構,修改數據表範式
- 重寫SQL 語句,讓優化器可以更優的執行
優化長難得查詢語句
- MySQL 內部每秒能掃描內存中上百萬行數據,相比之下,響應數據給客戶端就要慢得多
- 使用盡可能少的查詢是好的,但是有時將一個大的查詢分解爲多個小的查詢是很有必要的
- 分解關聯查詢,將一個關聯查詢分解爲多個sql 來執行,讓緩存效率更高,執行單個查詢可以減少鎖
的競爭,在應用層做關聯可以更容易對數據庫進行拆分,查詢效率會有大幅提升,較少冗餘記錄的查詢
優化特定類型的查詢語句
- 優化count()查詢,count(*)會忽略所有列,直接統計所有列數,因此不要用count(列名)
- 優化關聯查詢,確定ON 或者USING 子句的列上有索引;確保GROUP BY 和ORDER BY 中只有一
個表的列,這樣MySQL 纔有可能使用索引 - 優化子查詢建議使用關聯查詢替代
- 優化GROUP BY 和DISTINCT,建立索引進行優化
- 優化LIMIT 分頁,可以通過記錄上次查詢的最大ID,如果根據id 排序時,下次查詢根據該ID 來查
詢(如:ID > maxID) - 優化UNION 查詢,UNION ALL 性能比UNION 高
MySQL 提升(高可擴展和高可用)
分區表
工作原理
對用戶而言,分區表是一個獨立的邏輯表,但是底層MySQL 將其分成了多個物理子表,對於用戶來說是透明的,每一個分區表都會使用一個獨立的表文件。
創建表的時候使用partition by 子句定義每個分區存放的數據,執行查詢時,優化器會根據分區定義過濾那些沒有我們需要數據的分區,這樣查詢只需要查詢所需數據在的分區即可
分區的主要目的是將數據按照一個較粗的粒度分在不同的表中,這樣可以將相關的數據存放在一起,而且如果想一次性刪除整個分區的數據也很方便
適用場景
- 表非常大,無法全部存在內容,或者只有表的最後有熱點數據,其他都是歷史數據
- 分區表的數據更易維護,可以對獨立的分區進行獨立操作
- 分區表的數據可以分佈在不同機器上,從而高效使用資源
- 可以使用分區表來避免某些特殊瓶頸
- 可以備份和恢復獨立分區
限制
- 一個表最多隻能有1024 個分區
- 5.1 版本中,分區表表達式必須是整數,5.5 可以使用列分區
- 分區字段中如果有主見和唯一索引列,那麼主鍵和唯一列都必須包含進來
- 分區表中無法使用外鍵約束
- 需要對現有表的結構進行改變
- 所有分區都必須使用相同的存儲引擎
- 分區函數中可以使用的函數和表達式會有一些限制
- 某些存儲引擎不支持分區
- 對於MyISAM 的分區表,不能使用load index into cache
- 對於MyISAM 表,使用分區表時需要打開更多的文件描述符
分庫分表
工作原理:
通過一些HASH 算法或者工具實現將一張數據表垂直或者水平物理切分
適用場景
- 單表記錄條數達到百萬到千萬級別時
- 解決表鎖的問題
分表方式
- 水平切分:表很大,分割後可以減低在查詢時需要讀的數據和索引的頁數,同時也減低了索引的層數,提高查詢速度
使用場景:
1. 表中數據本身就有獨立性,例如表中分別記錄各個地區的數據或者不同時期的數據,特別是有些數據常用,有些不常用
2. 需要把數據存放在多個介質
缺點:
1. 給應用增加複雜度,通常查詢時需要多個表名,查詢所有數據都需要UNION 操作2. 在許多數據庫應用中,這種複雜性會超過他帶來的優點,查詢時會增加讀一個索引層的磁盤次數
- 垂直分表:把主鍵和一些列放在一個表,然後把主鍵和另外的列放在另一張表中
使用場景:
1. 如果一個表中某些列常用,而另外一些列不常用
2. 可以使數據行變小,一個數據頁能存儲更多數據,查詢時減少I/O 次數
缺點:
1. 管理冗餘列,查詢所有數據需要JOIN 操作2. 有些分表的策略基於應用層的邏輯算法,一旦邏輯算法改變,整個分表邏輯都會改變,擴展性較差3. 對於應用層來說,邏輯算法無疑增加開發成本
主從複製
工作原理
- 在主庫上把數據更改記錄到二進制日誌
- 從庫將主庫的日誌複製到自己的中繼日誌
- 從庫讀取中繼日誌中的事件,將其重放到從庫數據中
解決問題
- 數據分佈:隨意停止或開始複製,並在不同地理位置分佈數據備份
- 負載均衡:減低單個服務器壓力
- 高可用和故障切換:幫助應用程序避免單點失敗
- 升級測試:可以使用更高版本的MySQL 作爲從庫
MySQL 安全
安全操作
- 使用預處理語句防SQL 這幾日
- 寫入數據庫的數據要進行特殊字符轉移
- 查詢錯誤信息不要返回給用戶,將錯誤記錄到日誌
安全設置
- 定期做數據備份
- 不給查詢用戶root 權限,合理分配權限
- 關閉遠程訪問數據庫權限
- 修改root 口令,不用默認口令,使用較複雜的口令
- 刪除多餘的用戶
- 改變root 用戶的名稱
- 限制一般用戶瀏覽其他庫
- 限制用戶對數據文件的訪問權限
原文出處www.7php.cn