正確使用索引 資料庫表中添加索引後確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,如果以錯誤的方式使用,則即使建立索引也會不奏效。即使建立索引,索引也不會生效: 其他註意事項 limit分頁 無論是否有索引,limit分頁是一個值得關註的問題 1 每頁顯示10條: 2 當前 118 120, ...
正確使用索引
資料庫表中添加索引後確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,如果以錯誤的方式使用,則即使建立索引也會不奏效。
即使建立索引,索引也不會生效:
1 - like '%xx'
2 select * from tb1 where name like '%cn';
3 - 使用函數
4 select * from tb1 where reverse(name) = 'wupeiqi';
5 - or
6 select * from tb1 where nid = 1 or email = '[email protected]';
7 特別的:當or條件中有未建立索引的列才失效,以下會走索引
8 select * from tb1 where nid = 1 or name = 'seven';
9 select * from tb1 where nid = 1 or email = '[email protected]' and name = 'alex'
10 - 類型不一致
11 如果列是字元串類型,傳入條件是必須用引號引起來,不然...
12 select * from tb1 where name = 999;
13 - !=
14 select * from tb1 where name != 'alex'
15 特別的:如果是主鍵,則還是會走索引
16 select * from tb1 where nid != 123
17 - >
18 select * from tb1 where name > 'alex'
19 特別的:如果是主鍵或索引是整數類型,則還是會走索引
20 select * from tb1 where nid > 123
21 select * from tb1 where num > 123
22 - order by
23 select email from tb1 order by name desc;
24 當根據索引排序時候,選擇的映射如果不是索引,則不走索引
25 特別的:如果對主鍵排序,則還是走索引:
26 select * from tb1 order by nid desc;
27
28 - 組合索引最左首碼
29 如果組合索引為:(name,email)
30 name and email -- 使用索引
31 name -- 使用索引
32 email -- 不使用索引
其他註意事項
1 - 避免使用select *
2 - count(1)或count(列) 代替 count(*)
3 - 創建表時儘量時 char 代替 varchar
4 - 表的欄位順序固定長度的欄位優先
5 - 組合索引代替多個單列索引(經常使用多個條件查詢時)
6 - 儘量使用短索引
7 - 使用連接(JOIN)來代替子查詢(Sub-Queries)
8 - 連表時註意條件類型需一致
9 - 索引散列值(重覆少)不適合建索引,例:性別不適合
limit分頁
無論是否有索引,limit分頁是一個值得關註的問題
1 每頁顯示10條:
2 當前 118 120, 125
3
4 倒序:
5 大 小
6 970 7 6 6 5 54 43 32
7 19 98
8 下一頁:
9
10 select
11 *
12 from
13 tb1
14 where
15 nid < (select nid from (select nid from tb1 where nid < 當前頁最小值 order by nid desc limit 每頁數據 *【頁碼-當前頁】) A order by A.nid asc limit 1)
16 order by
17 nid desc
18 limit 10;
19
20
21
22 select
23 *
24 from
25 tb1
26 where
27 nid < (select nid from (select nid from tb1 where nid < 970 order by nid desc limit 40) A order by A.nid asc limit 1)
28 order by
29 nid desc
30 limit 10;
31
32
33 上一頁:
34
35 select
36 *
37 from
38 tb1
39 where
40 nid < (select nid from (select nid from tb1 where nid > 當前頁最大值 order by nid asc limit 每頁數據 *【當前頁-頁碼】) A order by A.nid asc limit 1)
41 order by
42 nid desc
43 limit 10;
44
45
46 select
47 *
48 from
49 tb1
50 where
51 nid < (select nid from (select nid from tb1 where nid > 980 order by nid asc limit 20) A order by A.nid desc limit 1)
52 order by
53 nid desc
54 limit 10;
View Code
執行計劃
explain + 查詢SQL - 用於顯示SQL執行信息參數,根據參考信息可以進行SQL優化
1 mysql> explain select * from tb2;
2 +----+-------------+-------+------+---------------+------+---------+------+------+-------+
3 | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
4 +----+-------------+-------+------+---------------+------+---------+------+------+-------+
5 | 1 | SIMPLE | tb2 | ALL | NULL | NULL | NULL | NULL | 2 | NULL |
6 +----+-------------+-------+------+---------------+------+---------+------+------+-------+
7 1 row in set (0.00 sec)
1 id
2 查詢順序標識
3 如:mysql> explain select * from (select nid,name from tb1 where nid < 10) as B;
4 +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
5 | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
6 +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
7 | 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 9 | NULL |
8 | 2 | DERIVED | tb1 | range | PRIMARY | PRIMARY | 8 | NULL | 9 | Using where |
9 +----+-------------+------------+-------+---------------+---------+---------+------+------+-------------+
10 特別的:如果使用union連接氣值可能為null
11
12
13 select_type
14 查詢類型
15 SIMPLE 簡單查詢
16 PRIMARY 最外層查詢
17 SUBQUERY 映射為子查詢
18 DERIVED 子查詢
19 UNION 聯合
20 UNION RESULT 使用聯合的結果
21 ...
22 table
23 正在訪問的表名
24
25
26 type
27 查詢時的訪問方式,性能:all < index < range < index_merge < ref_or_null < ref < eq_ref < system/const
28 ALL 全表掃描,對於數據表從頭到尾找一遍
29 select * from tb1;
30 特別的:如果有limit限制,則找到之後就不在繼續向下掃描
31 select * from tb1 where email = '[email protected]'
32 select * from tb1 where email = '[email protected]' limit 1;
33 雖然上述兩個語句都會進行全表掃描,第二句使用了limit,則找到一個後就不再繼續掃描。
34
35 INDEX 全索引掃描,對索引從頭到尾找一遍
36 select nid from tb1;
37
38 RANGE 對索引列進行範圍查找
39 select * from tb1 where name < 'alex';
40 PS:
41 between and
42 in
43 > >= < <= 操作
44 註意:!= 和 > 符號
45
46
47 INDEX_MERGE 合併索引,使用多個單列索引搜索
48 select * from tb1 where name = 'alex' or nid in (11,22,33);
49
50 REF 根據索引查找一個或多個值
51 select * from tb1 where name = 'seven';
52
53 EQ_REF 連接時使用primary key 或 unique類型
54 select tb2.nid,tb1.name from tb2 left join tb1 on tb2.nid = tb1.nid;
55
56
57
58 CONST 常量
59 表最多有一個匹配行,因為僅有一行,在這行的列值可被優化器剩餘部分認為是常數,const表很快,因為它們只讀取一次。
60 select nid from tb1 where nid = 2 ;
61
62 SYSTEM 系統
63 表僅有一行(=系統表)。這是const聯接類型的一個特例。
64 select * from (select nid from tb1 where nid = 1) as A;
65 possible_keys
66 可能使用的索引
67
68 key
69 真實使用的
70
71 key_len
72 MySQL中使用索引位元組長度
73
74 rows
75 mysql估計為了找到所需的行而要讀取的行數 ------ 只是預估值
76
77 extra
78 該列包含MySQL解決查詢的詳細信息
79 “Using index”
80 此值表示mysql將使用覆蓋索引,以避免訪問表。不要把覆蓋索引和index訪問類型弄混了。
81 “Using where”
82 這意味著mysql伺服器將在存儲引擎檢索行後再進行過濾,許多where條件里涉及索引中的列,當(並且如果)它讀取索引時,就能被存儲引擎檢驗,因此不是所有帶where子句的查詢都會顯示“Using where”。有時“Using where”的出現就是一個暗示:查詢可受益於不同的索引。
83 “Using temporary”
84 這意味著mysql在對查詢結果排序時會使用一個臨時表。
85 “Using filesort”
86 這意味著mysql會對結果使用一個外部索引排序,而不是按索引次序從表裡讀取行。mysql有兩種文件排序演算法,這兩種排序方式都可以在記憶體或者磁碟上完成,explain不會告訴你mysql將使用哪一種文件排序,也不會告訴你排序會在記憶體里還是磁碟上完成。
87 “Range checked for each record(index map: N)”
88 這個意味著沒有好用的索引,新的索引將在聯接的每一行上重新估算,N是顯示在possible_keys列中索引的點陣圖,並且是冗餘的。
詳細
慢日誌查詢
a、配置MySQL自動記錄慢日誌
1 slow_query_log = OFF 是否開啟慢日誌記錄
2 long_query_time = 2 時間限制,超過此時間,則記錄
3 slow_query_log_file = /usr/slow.log 日誌文件
4 log_queries_not_using_indexes = OFF 為使用索引的搜索是否記錄
註:查看當前配置信息:
show variables like '%query%'
修改當前配置:
set global 變數名 = 值
b、查看MySQL慢日誌
mysqldumpslow -s at -a /usr/local/var/mysql/MacBook-Pro-3-slow.log
1 """
2 --verbose 版本
3 --debug 調試
4 --help 幫助
5
6 -v 版本
7 -d 調試模式
8 -s ORDER 排序方式
9 what to sort by (al, at, ar, c, l, r, t), 'at' is default
10 al: average lock time
11 ar: average rows sent
12 at: average query time
13 c: count
14 l: lock time
15 r: rows sent
16 t: query time
17 -r 反轉順序,預設文件倒序拍。reverse the sort order (largest last instead of first)
18 -t NUM 顯示前N條just show the top n queries
19 -a 不要將SQL中數字轉換成N,字元串轉換成S。don't abstract all numbers to N and strings to 'S'
20 -n NUM abstract numbers with at least n digits within names
21 -g PATTERN 正則匹配;grep: only consider stmts that include this string
22 -h HOSTNAME mysql機器名或者IP;hostname of db server for *-slow.log filename (can be wildcard),
23 default is '*', i.e. match all
24 -i NAME name of server instance (if using mysql.server startup script)
25 -l 總時間中不減去鎖定時間;don't subtract lock time from total time
26 """