1. 程式人生 > >MySQL---正確使用索引、limit分頁、執行計劃、慢日誌查詢

MySQL---正確使用索引、limit分頁、執行計劃、慢日誌查詢

ngs 數據庫 配置 服務 esc 操作 com ora 條件

正確使用索引

數據庫表中添加索引後確實會讓查詢速度起飛,但前提必須是正確的使用索引來查詢,如果以錯誤的方式使用,則即使建立索引也會不奏效。
即使建立索引,索引也不會生效:

 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 """

MySQL---正確使用索引、limit分頁、執行計劃、慢日誌查詢