MySQL優化步 (InnoDB)

MySQL優化步 (InnoDB)

優化的優先級

  • 數據庫結構設計
  • SQL語句
  • 數據庫存儲引擎和選擇和參數配置
  • 系統選擇及優化
  • 硬件升級

圖書

  • MySQL必知必會
  • 高性能MySQL
  • 深刻淺出MySQL
  • MySQL排錯指南
  • MySQL管理之道-性能高估、高可用和監控(初版)
  • MySQL管理之道-性能高估、高可用和監控(第二版)
  • MySQL技術內幕

安裝嚮導中的選項

安裝過程當中的選擇html


調試方法

  • show status:提供服務器狀態信息
  • show engine innodb status 查看innodb引擎的服務器情況
  • show variables
  • EXPLAIN
  • show profile
  • performance_schema
  • show processlist
  • sql_no_cache
  • slow_query_log

show status

show [session|global] status
  • session: 當前鏈接,默認爲session
  • global: 自數據庫上次啓動至今

經常使用mysql

  • Connections: 試圖鏈接MySQL服務器的次數
  • Uptime:服務器工做時間
  • Slow_queries:慢查詢的次數
show status like 'Com_%' /*表示語句執行次數*/

show variables

EXPLAIN

mysql> explain select * from table_name;
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
| id | select_type | table      | type | possible_keys | key  | key_len | ref  | rows | Extra |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
|  1 | SIMPLE      | table_name | ALL  | NULL          | NULL | NULL    | NULL |    1 | NULL  |
+----+-------------+------------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)

字段說明id表示查詢中執行select子句或操做表的順序select_type查詢中每一個select子句的類型table輸出結果集的表type表示MySQL在表中找到的所需行的方式,或者叫訪問類型possible_keys表示查詢時可能使用的索引key表示實際使用的索引,若沒有使用索引,顯示爲NULLkey_len使用到索引字段的字節數(長度)ref表示上述表的鏈接匹配條件,即哪些列或常量被用於查找索引列上的值rows掃描行的數量Extra包含不適合在其餘列中顯示但十分重要的額外信息sql

id

  1. id相同,執行順序由上至下
  2. 若是是子查詢,id的序號會遞增,id值越大優先級越高,越先被執行
  3. id若是相同,能夠認爲是一組,從上往下順序執行;在全部組中,id值越大,優先級越高,越先執行

select_type

字段說明SIMPLE簡單的SELECT語句(沒有使用 union 或者 子查詢)PRIMARY查詢中若包含任何複雜的子部分,最外層的select被標記爲PRIMARYUNION在一個UNION語句中第二或以後的SELECT語句DEPENDENT UNION在一個UNION語句中第二或以後的SELECT語句,取決於外層的查詢UNION RESULTUNION的結果集SUBQUERY子查詢中的第一個SELECTDEPENDENT SUBQUERY子查詢中的第一個SELECT,取決於外面的查詢DERIVED派生表的SELECT, FROM子句的子查詢UNCACHEABLE SUBQUERY不能將結果緩存的子查詢,必須從新計算外部查詢的每一行UNCACHEABLE UNION在一個UNION中第二或以後的SELECT查詢屬於UNCACHEABLE SUBQUERY(請看UNCACHEABLE SUBQUERY)數據庫

說明:緩存

  • DEPENDENT:典型表明就是使用了相關子查詢。(相關子查詢:子查詢裏包含了一個同時在子查詢裏,又在外部查詢的表的查詢)
  • DEPENDENT SUBQUERY: 它不一樣於UNCACHEABLE SUBQUERY的求值。對於DEPENDENT SUBQUERY,子查詢對於外部上下文裏每個集合中不一樣的變星值僅僅從新計算一次。而對於UNCACHEABLE SUBQUERY,子查詢對於外部上下文裏的每一行都會從新計算一次.

type

經常使用的類型有(從左到右,性能從差到好):服務器

+-----+-------+-------+------+--------+----------------+------+
| ALL | index | range | ref  | eq_ref | const, system  | NULL |
+-----+-------+-------+------+--------+----------------+------+

字段說明ALL全表掃描,MySQL遍歷全表來找到匹配的行index索引全掃描,MySQL遍歷整個索引來查詢匹配的行,index與ALL區別爲index類型只遍歷索引樹。range索引範圍掃描,只檢索給定範圍的行,使用一個索引來選擇行,常見於<、<=、>、>=、between等操做符。ref使用非惟一索引掃描或惟一索引的前綴掃描,返回匹配某個單獨值的記錄行eq_ref相似ref,區別就在使用的索引是惟一索引,對於每一個索引鍵值,表中只有一條記錄匹配,簡單來講,就是多表鏈接中使用primary key或者 unique key做爲關聯條件const, system當MySQL對查詢某部分進行優化,並轉換爲一個常量時,使用這些類型訪問。如將主鍵置於where列表中,MySQL就能將該查詢轉換爲一個常量NULLMySQL在優化過程當中分解語句,執行時甚至不用訪問表或索引,例如從一個索引列裏選取最小值能夠經過單獨索引查找完成。session

explain extended和show warnings

explain 的extended 擴展可以在本來explain的基礎上額外的提供一些查詢優化的信息,這些信息能夠經過MySQL的show warnings命令獲得。數據庫設計

官方說明函數

show profile

使用show profileshow profiles咱們能夠更清楚的瞭解SQL執行的過程。工具

  • 執行過程
  1. set profiling = 1 # 打開profiling
  2. 執行查詢
  3. show profiles;
  4. 經過show profile for query N語句可以看到執行過程當中線程的每一個狀態和消耗的時間。

performance_schema

  • 能夠代替show profile
  • 5.5最好不用,性能有問題, 5.6之後建議開啓

no_sql_cache

SQL_NO_CACHE的真正做用是禁止緩存查詢結果,但並不意味着cache不做爲結果返回給query。

使用方法:select no_sql_cache ...

show full processlist

能夠用語句SELECT * FROM information_schema.processlist代替show full processlist並能夠過慮想要的數據。

字段說明id不用說了吧,一個標識,你要kill一個語句的時候頗有用。user顯示單前用戶,若是不是root,這個命令就只顯示你權限範圍內的sql語句。host顯示這個語句是從哪一個ip的哪一個端口上發出的。呵呵,能夠用來追蹤出問題語句的用戶。db顯示這個進程目前鏈接的是哪一個數據庫。command列,顯示當前鏈接的執行的命令,通常就是休眠(sleep),查詢(query),鏈接(connect)。time此這個狀態持續的時間,單位是秒。state顯示使用當前鏈接的sql語句的狀態,很重要的列,後續會有全部的狀態的描述,請注意,state只是語句執行中的某一個狀態,一個sql語句,已查詢爲例,可能須要通過copying to tmp table,Sorting result,Sending data等狀態才能夠完成。info顯示這個sql語句,由於長度有限,因此長的sql語句就顯示不全,可是一個判斷問題語句的重要依據。

slow_query_log

使用show variables like '%slow%';查看是否啓用慢查詢。

參數說明slow_query_log指定是否開啓慢查詢日誌long_query_time設定慢查詢的閥值,超出次設定值的SQL即被記錄到慢查詢日誌,缺省值爲10sslow_query_log_file指定慢日誌文件存放位置,能夠爲空,系統會給一個缺省的文件host_name-slow.logmin_examined_row_limit:查詢檢查返回少於該參數指定行的SQL不被記錄到慢查詢日誌log_queries_not_using_indexes不使用索引的慢查詢日誌是否記錄到索引

打開慢查詢配置

slow_query_log = 1 
slow_query_log_file
long_query_time = 2
log_queries_not_using_indexes
log_slow_queries=/data/3306/slow-log.log

慢查詢日誌分析工具

  • mysqldumpslow

    • mysqldumpslow -s -r -t 10 slow-mysql.log

      • -s order (c,t,1,r,at,al,ar) 指定按哪一種排序方式輸出結果
      • -t top 指定取前幾條做爲結束輸出
  • pt-query-digest

    • pt-query-digest --explain h=127.0.0.1,u=root, p=password slow-mysql.log

優化數據庫(最重要)

目的

  • 減小數據冗餘
  • 儘可能避免數據維護中出現插入、更新、刪除異常
  • 節約數據存儲空間
  • 提升查詢效率

數據庫設計步驟

  • 需求分析:全面瞭解產品的存儲需求
  • 邏輯設計:設計數據的邏輯存儲結構,數據實體之間的邏輯關係,解決數據冗餘和數據維護異常
  • 物理設計:根據數據庫特色進行表結構設計(關係型數據庫、非關係型數據庫、存儲引擎)
  • 維護優化:根據實際狀況對索引、存儲結構等進行優化

範式

遵循三範式就能夠設計出符合需求的數據庫結構,符合,不是最優的。

  • 1NF:

    • 數據庫表中的字段都是單一屬性的,不可再分。
    • 單一屬性的列是由基本的數據類型所構成的
    • 設計出來的表都是簡單的二維表
  • 2NF:首先是 1NF,另外包含兩部份內容,一是表必須有一個主鍵;二是沒有包含在主鍵中的列必須徹底依賴於主鍵,而不能只依賴於主鍵的一部分。

  • 3NF:首先是 2NF,另外非主鍵列必須直接依賴於主鍵,不能存在傳遞依賴。即不能存在:非主鍵列 A 依賴於非主鍵列 B,非主鍵列 B 依賴於主鍵的狀況。

在設計數據庫中要最大程序的遵照三範式,特別是對於OLTP型的系統。

注意:三範式最大的問題在於查詢時一般須要Join不少表,而這會致使查詢效率很低,因此有時候基於性能考慮,咱們須要有意違反三範式,適度的作冗餘。

最多見的反範式化的數據的方法是複製或者緩存,在不一樣的表中存儲相同的特定列,使用觸發器更新緩存值。 另外一個從父表冗餘一些數據到的理由是排序的須要。

經過觸發器

表設計

  1. 更小的一般更好,通常狀況下,應該儘可能使用能夠正確存儲數據的最小數據類型。
  2. 簡單的數據類型,簡單數據類型一般須要更好的CPU週期。
  3. 儘可能避免使用NULL,一般狀況下最好指定列爲NOT NULL,除非直接的城崾存儲NUL值。注意:把可爲NULL的列改成NOT NULL帶來的恨不能提高比較小,沒有必要首先在現有的schema中查找並修改掉這種狀況。可是,若是計劃在列上建索引,就應該儘可能避免設計成可爲NULL的列。
  4. 避免太多的列。
  5. 避免太多的關聯,單個查詢最好在12個表之內作關聯,最多爲61個表。

不在數據庫中存儲圖片、文件等 全部字段均定義爲NOT NULL ,除非你真的想存Null 字段類型在知足需求條件下越小越好,使用UNSIGNED存儲非負整數 ,實際使用時候存儲負數場景很少 使用TIMESTAMP存儲時間 使用varchar存儲變長字符串 ,固然要注意varchar(M)裏的M指的是字符數不是字節數;使用UNSIGNED INT存儲IPv4 地址而不是CHAR(15) ,這種方式只能存儲IPv4,存儲不了IPv6 使用DECIMAL存儲精確浮點數,用float有的時候會有問題 少用blob text

字段類型的選取

整數類型

類型存儲空間存儲範圍存儲範圍數值TINYINT8-27~ 27-1-128~127SMALLINT16-215~ 215-1-32768~32767MEDIUMINT24-223~ 223-1-8388608~8388607INT32-231~ 231-1-2147483648~2147483647BIGINT64-263~ 263-1-9223372036854775808~9223372036854775807

有符號和無符號使用相同的存儲空間,並具備相同的功能,若是不容許負值,大體可使正數的上限提升一倍。

使用整數來存儲IPV4,它實際是32位無符號整數,不是字符串,使用小數點將地址發成四段只是爲了讓人員閱讀,經過INET_ATON()和INET_NTOA()函數進行轉換。

相關文章
相關標籤/搜索