想要得到更好的表現,你須要: 合理的表結構 + 出色的索引 + [ 不錯的查詢語句]
不少時候你其實在向數據庫請求了超多資源,可能你並無意識到,這些多餘的數據會被拋棄,並給MySQL服務器端增長額外的壓力。 一些場景:html
-- 使用索引
EXPLAIN SELECT * FROM users WHERE id = 1\G
********************** 1.row **********************
type: ref
key : id
rows: 10
-- 刪除索引
EXPLAIN SELECT * FROM users WHERE id = 1\G
********************** 1.row ***********************
type: ALL
rows: 5073
extra: Using Where
複製代碼
咱們能夠經過"EXPLAIN" 命令看看這條命令是怎麼執行的,有沒有索引掃描內容真的差異太大mysql
在表面上,咱們都直接在 SQL 語句加上WHERE就完事兒,並不過多的去關心性能問題,可是即便你們都是WHERE, 在"索引" 的輔助下也會存在很大的優劣之分sql
由好到差:數據庫
總結一下,不管是方法1.存儲引擎能直接訪問須要的行,仍是2.直接前往B-Tree讀數,都好過全表掃描,返回全部數據而後由MySQL作過濾。 爲了達到這樣的效果,儘量把要用到的WHERE篩選項放到索引中去緩存
爲了更好的作出優化,以及後面會提到的"緩存命中",咱們必須也要先知道查詢過程是怎樣的。 關於詳細的步驟,咱們會在下面的環節描述一下各個部件是怎麼工做的bash
MySQL客戶端與MySQL服務器之間的交互是半雙工的,也就是說同一時刻內只有其中一方向另外一方發送請求,這個請求能夠是客戶端向服務器發送SQL語句,也能夠是服務器向客戶端返回所請求的數據,一旦客戶端發送了請求之後,它所能作的就只有等待服務器返回所請求的數據服務器
在解析一個SQL語句以前服務器會先看看是否有命中緩存中的數據,也就是看看是否已經有緩存上了。檢查的標準是經過對查詢語句的哈希實現的,若是哈希出的結果是同樣的就算命中,而且這個哈希是對大小寫敏感的,也就是說哪怕是大小寫不一致都不能算命中性能
MySQL服務器經過關鍵字將客戶端發來的SQL語句進行解析,解析器經過MYSQL語法對這條語句進行驗證,例如它將驗證是否使用了錯誤的關鍵字,關鍵字順序是否正確等。優化
預處理器則會去檢查它所請求的數據表以及列是否存在,並驗證權限。spa
走到了這一步說明你的語句沒有問題,能執行,問題就是怎麼執行。 因此查詢優化器,會先找出不少個可能的作法,並嘗試找出最優解 優化原則? 找出成本最低的
mysql > SELECT SQL_NO_CACHE COUNT(*) FROM users
+----------+
| count(*) |
+----------+
| 5462 |
+----------+
mysql > SHOW STATUS LIKE 'Last_query_cost'
+-----------------+-------------+
| Variable_name | Value |
+-----------------+-------------+
| Last_query_cost | 1040.59 |
+-----------------+-------------+複製代碼
2.5.1 先簡單介紹一下聯表的執行過程 (若是你知道就能夠跳過了)
-- 上圖反應的就是下面個SQL語句的聯表過程
SELECT tbl1.col1 , tbl2.col2
FROM tbl1 JOIN tbl2 USING(col3)
WHERE tbl1.col1 IN(5,6)複製代碼
表之間的關聯遵循一種"嵌套" 的規則,用最簡單的話說就是先取表[tbl1]的第一行,去表[tbl2]中作匹配,對於咱們,咱們天然是但願執行的步驟越少越好:
2.5.2 聯表優化實戰分析
SELECT tbl1.col1, tbl2.col2, tbl3.col3
FROM tbl1
INNER JOIN tbl2 USING(tbl1.col1)
INNER JOIN tbl3 USING(tbl3.col3);複製代碼