mysql的這些坑你踩過嗎?快來看看怎麼優化mysql?

什麼是mysql?

  • 若是你的回答是關係型數據庫,那就會顯得有些淺薄。咱們平時工做中確定會用到mysql,可是談到mysql,就不能只說增刪改查。
  • 接下來咱們從另外一個角度認識一下mysql(其實不只僅是mysql,對於任何一個產品、服務,咱們都應該有一個抽象化的架構,而不能侷限於這個產品的某一個區域)

mysql的邏輯分層

mysql的這些坑你踩過嗎?快來看看怎麼優化mysql?

 

  • 鏈接層:提供客戶端的鏈接功能和權限認證,
  • 服務層: 提供用戶使用的接口(curd,主從配置,數據備份等) sql優化器(mysql query optimizer)
# 聯合索引 a b c 
select * from table1 where a=xxx and c=xxx and b=xxx;#通過優化器優化後可使用索引,
複製代碼
  • 引擎層 :提供存儲數據的方式(innodb myisam archive ,memory,csv,federated ),Mysql在V5.1以前默認存儲引擎是MyISAM;在此以後默認存儲引擎是InnoDB,myisam 和innodb的區別:https://segmentfault.com/a/1190000021995700
mysql的這些坑你踩過嗎?快來看看怎麼優化mysql?

 

mysql> show engines
    -> ;
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+
| Engine | Support | Comment | Transactions | XA | Savepoints | +--------------------+---------+----------------------------------------------------------------+--------------+------+------------+ | InnoDB             | DEFAULT | Supports transactions, row-level locking, and foreign keys     | YES | YES  | YES |
| MRG_MYISAM | YES     | Collection of identical MyISAM tables | NO           | NO | NO         | | MEMORY             | YES | Hash based, stored in memory, useful for temporary tables      | NO | NO   | NO |
| BLACKHOLE | YES     | /dev/null storage engine (anything you write to it disappears) | NO           | NO | NO         | | MyISAM             | YES | MyISAM storage engine                                          | NO | NO   | NO |
| CSV | YES     | CSV storage engine | NO           | NO | NO         | | ARCHIVE            | YES | Archive storage engine                                         | NO | NO   | NO |
| PERFORMANCE_SCHEMA | YES     | Performance Schema | NO           | NO | NO         | | FEDERATED          | NO | Federated MySQL storage engine                                 | NULL | NULL | NULL |
+--------------------+---------+----------------------------------------------------------------+--------------+------+------------+

mysql> show variables like '%storage_engine%';
+----------------------------------+--------+
| Variable_name | Value  | +----------------------------------+--------+ | default_storage_engine           | InnoDB |
| default_tmp_storage_engine | InnoDB | | disabled_storage_engines         | |
| internal_tmp_disk_storage_engine | InnoDB | +----------------------------------+--------+ 複製代碼

TODO 具體存儲引擎和相關使用場景待補充php

  • 存儲層

mysql的索引類型

Mysql支持的索引類型:咱們最經常使用的是B-TREE索引,可是mysql還有另一種索引,就是HASH索引https://blog.csdn.net/oChangWen/article/details/54024063html

# hash
create table testhash(
fname varchar(50) not null,
lname varchar(50) not null,
key using hash(fname)) engine=memory;

# b-tree
CREATE TABLE t(
  aid int unsigned not null auto_increment,
  userid int unsigned not null default 0,
  username varchar(20) not null default ‘’,
  detail varchar(255) not null default ‘’,
  primary key(aid),
  unique key(uid) USING BTREE,
  key (username(12)) USING BTREE — 此處 uname 列只建立了最左12個字符長度的部分索引
)engine=InnoDB;
複製代碼

 

mysql的這些坑你踩過嗎?快來看看怎麼優化mysql?

 

mysql的這些坑你踩過嗎?快來看看怎麼優化mysql?

 

  • 使用場景
mysql的這些坑你踩過嗎?快來看看怎麼優化mysql?

 

  • b-tree 索引原理示意圖(二叉樹爲例) 中序

 

mysql的這些坑你踩過嗎?快來看看怎麼優化mysql?

 

mysql的這些坑你踩過嗎?

  • 建立數據表,插入數據
CREATE TABLE `t_user` (
                               `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵Id',
                               `name` varchar(30) DEFAULT NULL COMMENT '姓名',
                               `email` varchar(30) DEFAULT NULL COMMENT '郵箱',
                               `age` int(11) DEFAULT NULL COMMENT '年齡',
                               `telephone` varchar(30) DEFAULT NULL COMMENT '電話',
                               `status` tinyint(4) DEFAULT NULL COMMENT '0:正常 1:下線 ',
                               `created_at` datetime DEFAULT CURRENT_TIMESTAMP comment '建立時間',
                               `updated_at` datetime DEFAULT CURRENT_TIMESTAMP comment '更新時間',
                               PRIMARY KEY (`id`),
                               KEY `idx_email` (`email`),
                               KEY `idx_name` (`name`),
                               KEY `idx_telephone` (`telephone`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4;

# 插入一條數據
INSERT INTO test.t_user (name, email, age, telephone, status, created_at, updated_at) VALUES ('jimi', 'ffdsa', 11, '15001262936', 0, DEFAULT, DEFAULT);
# 批量插入數據
INSERT INTO test.t_user  select  null,  name, email, age, telephone, 0, null, null from t_user;

複製代碼
  • 字符串轉數字,經過如下能夠看到,主鍵id的類型是int,可是 查詢的關鍵字是string,這個時候就會轉換
mysql> select * from t_user where id='2424786gafafdfdsa';
+---------+------+-------+------+-------------+--------+------------+------------+
| id | name | email | age  | telephone | status | created_at | updated_at | +---------+------+-------+------+-------------+--------+------------+------------+ | 2424786 | jimi | ffdsa | 11 | 15001262936 | 0 | NULL       | NULL |
+---------+------+-------+------+-------------+--------+------------+------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain  select * from t_user where id='2426gafafdfdsa';
+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+ |  1 | SIMPLE | t_user | NULL | const | PRIMARY | PRIMARY | 4 | const | 1 |   100.00 | NULL |
+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 2 warnings (0.00 sec)
複製代碼
  • 字符串類型的字段0會全匹配
mysql> select * from t_user where  email=0 limit 10;
+----+------+-------+------+-------------+--------+---------------------+---------------------+
| id | name | email | age  | telephone | status | created_at | updated_at          | +----+------+-------+------+-------------+--------+---------------------+---------------------+ |  2 | jimi | ffdsa | 11 | 15001262936 | 0 | 2020-11-27 14:33:57 | 2020-11-27 14:33:57 |
| 3 | jimi | ffdsa |   11 | 15001262936 |      0 | NULL | NULL                | |  4 | jimi | ffdsa | 11 | 15001262936 | 0 | NULL                | NULL |
| 5 | jimi | ffdsa |   11 | 15001262936 |      0 | NULL | NULL                | |  7 | jimi | ffdsa | 11 | 15001262936 | 0 | NULL                | NULL |
| 8 | jimi | ffdsa |   11 | 15001262936 |      0 | NULL | NULL                | |  9 | jimi | ffdsa | 11 | 15001262936 | 0 | NULL                | NULL |
| 10 | jimi | ffdsa |   11 | 15001262936 |      0 | NULL | NULL                | | 14 | jimi | ffdsa | 11 | 15001262936 | 0 | NULL                | NULL |
| 15 | jimi | ffdsa |   11 | 15001262936 |      0 | NULL | NULL                | +----+------+-------+------+-------------+--------+---------------------+---------------------+ 10 rows in set, 10 warnings (0.00 sec) 複製代碼
  • 大小寫敏感問題(形成線上緩存擊穿,如語音模塊,視頻模塊已控制)
mysql> select * from t_user where email='ffdsaADFG';
+---------+------+-----------+------+-------------+--------+------------+------------+
| id | name | email | age  | telephone | status | created_at | updated_at | +---------+------+-----------+------+-------------+--------+------------+------------+ | 2424786 | jimi | ffdsaADFG | 11 | 15001262936 | 0 | NULL       | NULL |
+---------+------+-----------+------+-------------+--------+------------+------------+
1 row in set (0.00 sec)

mysql> select * from t_user where email='ffdsaadfg';
+---------+------+-----------+------+-------------+--------+------------+------------+
| id | name | email | age  | telephone | status | created_at | updated_at | +---------+------+-----------+------+-------------+--------+------------+------------+ | 2424786 | jimi | ffdsaADFG | 11 | 15001262936 | 0 | NULL       | NULL |
+---------+------+-----------+------+-------------+--------+------------+------------+
1 row in set (0.00 sec)

# 解決大小寫問題
#utf8_general_ci,表示不區分大小寫;utf8_general_cs表示區分大小寫;utf8_bin表示二進制比較,也能夠比較大小寫
ALTER TABLE t_user MODIFY COLUMN email VARCHAR(30) BINARY CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL;
mysql> select * from t_user where email='ffdsaadfg';
Empty set (0.00 sec)
複製代碼
  • 數字轉字符串,可是這種轉化是用不上索引的
mysql> select * from t_user where email=123;

;
+---------+------+--------+------+-------------+--------+------------+------------+
| id | name | email | age  | telephone | status | created_at | updated_at | +---------+------+--------+------+-------------+--------+------------+------------+ | 2424789 | jimi | 123abc | 11 | 15001262936 | 0 | NULL       | NULL |
+---------+------+--------+------+-------------+--------+------------+------------+
1 row in set, 65535 warnings (2.57 sec)

mysql> explain  select * from t_user where email=123;
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows    | filtered | Extra       | +----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+ |  1 | SIMPLE | t_user | NULL | ALL  | idx_email | NULL | NULL | NULL | 2090340 |    10.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
1 row in set, 3 warnings (0.00 sec)
複製代碼

做爲一個phper,此處也吐槽一下php的弱類型

/** * Notes:布爾類型轉換 * User: zhangguofu * Date: 2020/12/1 * Time: 4:35 下午 */
    public function test1() {
        $a = 2;
        $b = 3;
        if ($a = 3 || $b = 6) {
            $a++;
            $b++;
        }
        echo $a . " " . $b;//1 4
    }

    /** * Notes:字符串 數字類型轉換 * User: zhangguofu * Date: 2020/11/26 * Time: 8:01 下午 */
    public function test2() {
        $a = 'a';
        $b = 'b';
        $a++;
        var_dump($a == $b);//true
    }

/** * Notes:字符串 數字 弱類型對比和轉換 * User: zhangguofu * Date: 2020/12/4 * Time: 3:12 下午 */
    function test3() {
        var_dump(md5('240610708') == md5('QNKCDZO')); //true

        var_dump("admin" == 0);  //true
        var_dump("1admin" == 1); //true
        var_dump("admin1" == 1);//false
        var_dump("admin1" == 0);//true
        var_dump("0e123456" == "0e4456789"); //true

        var_dump(0 == "a"); // 0 == 0 -> true
        var_dump("1" == "01"); // 1 == 1 -> true
        var_dump("10" == "1e1"); // 10 == 10 -> true
        var_dump(100 == "1e2"); // 100 == 100 -> true
    }


複製代碼

怎麼優化mysql?Explain 分析查看mysql性能

mysql> explain  select * from t_user where email=123;
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows    | filtered | Extra       | +----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+ |  1 | SIMPLE | t_user | NULL | ALL  | idx_email | NULL | NULL | NULL | 2090340 |    10.00 | Using where |
+----+-------------+--------+------------+------+---------------+------+---------+------+---------+----------+-------------+
複製代碼

id : 編號 select_type :查詢類型 table :表 type :類型 possible_keys :預測用到的索引 key :實際使用的索引 key_len :實際使用索引的長度
ref :表之間的引用 rows :經過索引查詢到的數據量 Extra :額外的信息

  • 解釋: 插入數據
#課程表
create table course
(
cid int(3),
cname varchar(20),
tid int(3)
);
#教師表
create table teacher
(
tid int(3),
tname varchar(20),
tcid int(3)
);
# 教師證
create table teacherCard
(
tcid int(3),
tcdesc varchar(200)
);


insert into course values(1,'java',1);
insert into course values(2,'html',1);
insert into course values(3,'sql',2);
insert into course values(4,'web',3);

insert into teacher values(1,'tz',1);
insert into teacher values(2,'tw',2);
insert into teacher values(3,'tl',3);

insert into teacherCard values(1,'tzdesc') ;
insert into teacherCard values(2,'twdesc') ;
insert into teacherCard values(3,'tldesc') ;

複製代碼
  • id: id值相同,從上往下 順序執行。id值不一樣:id值越大越優先查詢 (本質:在嵌套子查詢時,先查內層 再查外層)
mysql> explain select tc.tcdesc from teacherCard tc,course c,teacher t where c.tid = t.tid
    -> and t.tcid = tc.tcid and c.cid = 2 or tc.tcid=3 ;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra                                              | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+ |  1 | SIMPLE | tc    | NULL | ALL  | NULL | NULL | NULL | NULL | 3 |   100.00 | NULL |
| 1 | SIMPLE      | t | NULL       | ALL | NULL          | NULL | NULL    | NULL |    3 | 100.00 | Using where; Using join buffer (Block Nested Loop) | |  1 | SIMPLE | c     | NULL | ALL  | NULL | NULL | NULL | NULL | 4 |   100.00 | Using where; Using join buffer (Block Nested Loop) |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+----------------------------------------------------+
3 rows in set, 1 warning (0.00 sec)

複製代碼
  • select_type:查詢類型

simple 簡單子查詢,不包含子查詢和union primary 包含union或者子查詢,最外層的部分標記爲primary subquery 通常子查詢中的子查詢被標記爲subquery,也就是位於select列表中的查詢 derived 派生表——該臨時表是從子查詢派生出來的,位於form中的子查詢 union 位於union中第二個及其之後的子查詢被標記爲union,第一個就被標記爲primary若是是union位於from中則標記爲derived union result 用來從匿名臨時表裏檢索結果的select被標記爲union result dependent union 顧名思義,首先須要知足UNION的條件,及UNION中第二個以及後面的SELECT語句,同時該語句依賴外部的查詢 subquery 子查詢中第一個SELECT語句 dependent subquery 和DEPENDENT UNION相對UNION同樣java

mysql> explain select * from   teacherCard limit 1;
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+ |  1 | SIMPLE | teacherCard | NULL | ALL  | NULL | NULL | NULL | NULL | 3 |   100.00 | NULL |
+----+-------------+-------------+------------+------+---------------+------+---------+------+------+----------+-------+


mysql> explain select  cr.cname from ( select * from course where tid = 1  union select * from course where tid = 2 ) cr ;
+----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+
| id | select_type  | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra           | +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+ |  1 | PRIMARY | <derived2> | NULL | ALL  | NULL | NULL | NULL | NULL | 4 |   100.00 | NULL |
| 2 | DERIVED      | course | NULL       | ALL | NULL          | NULL | NULL    | NULL |    4 | 25.00 | Using where     | |  3 | UNION | course     | NULL | ALL  | NULL | NULL | NULL | NULL | 4 |    25.00 | Using where |
| NULL | UNION RESULT | <union2,3> | NULL       | ALL | NULL          | NULL | NULL    | NULL | NULL | NULL | Using temporary | +----+--------------+------------+------------+------+---------------+------+---------+------+------+----------+-----------------+ 複製代碼
  • type

system: 只有一條數據的系統表 ;或 衍生表只有一條數據的主查詢 const:僅僅能查到一條數據的SQL ,用於Primary key 或unique索引 (類型 與索引類型有關)mysql

mysql> create table test01
    -> (
    -> tid int(3), -> tname varchar(20) -> );
Query OK, 0 rows affected (0.04 sec) mysql> mysql> insert into test01 values(1,'a') ;
Query OK, 1 row affected (0.01 sec) mysql> alter table test01 add constraint tid_pk primary key(tid) ;
Query OK, 0 rows affected (0.15 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> explain select * from (select * from test01 )t where tid =1 ;
+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table  | partitions | type  | possible_keys | key     | key_len | ref   | rows | filtered | Extra |
+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
|  1 | SIMPLE      | test01 | NULL       | const | PRIMARY       | PRIMARY | 4       | const |    1 |   100.00 | NULL  |
+----+-------------+--------+------------+-------+---------------+---------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
複製代碼

ref:非惟一性索引,對於每一個索引鍵的查詢,返回匹配的全部行(0,多)android

mysql>
mysql> alter table test01 drop primary key ;
Query OK, 1 row affected (0.08 sec)
Records: 1  Duplicates: 0  Warnings: 0

mysql> create index test01_index on test01(tid) ;
Query OK, 0 rows affected (0.04 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select * from (select * from test01 )t where tid =1 ;
+----+-------------+--------+------------+------+---------------+--------------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------+------------+------+---------------+--------------+---------+-------+------+----------+-------+ |  1 | SIMPLE | test01 | NULL | ref  | test01_index | test01_index | 4 | const | 1 |   100.00 | NULL |
+----+-------------+--------+------------+------+---------------+--------------+---------+-------+------+----------+-------+
複製代碼

eq_ref:惟一性索引:對於每一個索引鍵的查詢,返回匹配惟一行數據(有且只有1個,不能多 、不能0)ios

mysql>  alter table teacherCard add constraint pk_tcid primary key(tcid);
ERROR 1068 (42000): Multiple primary key defined
mysql> alter table teacher add constraint uk_tcid unique index(tcid) ;
ERROR 1061 (42000): Duplicate key name 'uk_tcid'
mysql>
mysql>
mysql> explain select t.tcid from teacher t,teacherCard tc where t.tcid = tc.tcid ;
+----+-------------+-------+------------+--------+---------------+---------+---------+-------------+------+----------+--------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra                    | +----+-------------+-------+------------+--------+---------------+---------+---------+-------------+------+----------+--------------------------+ |  1 | SIMPLE | t     | NULL | index  | uk_tcid | uk_tcid | 5 | NULL        | 3 |   100.00 | Using where; Using index |
| 1 | SIMPLE      | tc | NULL       | eq_ref | PRIMARY       | PRIMARY | 4       | test.t.tcid |    1 | 100.00 | Using index              | +----+-------------+-------+------------+--------+---------------+---------+---------+-------------+------+----------+--------------------------+ 2 rows in set, 1 warning (0.00 sec) 複製代碼

range:檢索指定範圍的行 ,where後面是一個範圍查詢(between ,> < >=, 特殊:in有時候會失效 ,從而轉爲 無索引all--5.7之前的版本)web

mysql> alter table teacher add index tid_index (tid) ;
Query OK, 0 rows affected (0.02 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select t.* from teacher t where t.tid in (1,2) ;
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra       | +----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+ |  1 | SIMPLE | t     | NULL | ALL  | tid_index | NULL | NULL | NULL | 3 |    66.67 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> explain select t.* from teacher t where t.tid <3 ;
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra                 | +----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+ |  1 | SIMPLE | t     | NULL | range | tid_index | tid_index | 5 | NULL | 2 |   100.00 | Using index condition |
+----+-------------+-------+------------+-------+---------------+-----------+---------+------+------+----------+-----------------------+
1 row in set, 1 warning (0.00 sec)

複製代碼

index:查詢所有索引中數據,不須要回表查找,黃金索引面試

mysql> explain select tid from teacher ;
+----+-------------+---------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra       | +----+-------------+---------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+ |  1 | SIMPLE | teacher | NULL | index | NULL | tid_index | 5 | NULL | 3 |   100.00 | Using index |
+----+-------------+---------+------------+-------+---------------+-----------+---------+------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
複製代碼

all:查詢所有表中的數據,全表掃描sql

mysql> explain select *  from teacher
    -> ;
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+ |  1 | SIMPLE | teacher | NULL | ALL  | NULL | NULL | NULL | NULL | 3 |   100.00 | NULL |
+----+-------------+---------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)
複製代碼
  • possible_keys :可能用到的索引,是一種預測,不許。
mysql> explain select tc.tcdesc from teacherCard tc,course c,teacher t where c.tid = t.tid
    -> and t.tcid = tc.tcid and c.cname = 'sql' ;
+----+-------------+-------+------------+--------+-------------------+-----------+---------+-------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys     | key | key_len | ref | rows | filtered | Extra       | +----+-------------+-------+------------+--------+-------------------+-----------+---------+-------------+------+----------+-------------+ |  1 | SIMPLE | c     | NULL | ALL    | NULL | NULL      | NULL | NULL        | 4 |    25.00 | Using where |
| 1 | SIMPLE      | t | NULL       | ref | uk_tcid,tid_index | tid_index | 5       | test.c.tid |    1 | 100.00 | Using where | |  1 | SIMPLE | tc    | NULL | eq_ref | PRIMARY | PRIMARY   | 4 | test.t.tcid | 1 |   100.00 | NULL |
+----+-------------+-------+------------+--------+-------------------+-----------+---------+-------------+------+----------+-------------+
3 rows in set, 1 warning (0.00 sec)
複製代碼
  • key :實際使用到的索引
  • key_len :索引的長度 ; 做用:用於判斷複合索引是否被徹底使用 (a,b,c)。
mysql> create table test_kl
    -> (
    -> name char(20) not null default ''
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> alter table test_kl add index index_name(name) ;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select * from test_kl where name =''
    -> ;
+----+-------------+---------+------------+------+---------------+------------+---------+-------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra       | +----+-------------+---------+------------+------+---------------+------------+---------+-------+------+----------+-------------+ |  1 | SIMPLE | test_kl | NULL | ref  | index_name | index_name | 80 | const | 1 |   100.00 | Using index |
+----+-------------+---------+------------+------+---------------+------------+---------+-------+------+----------+-------------+
1 row in set, 1 warning (0.00 sec)

mysql> show variables like '%char%';
+--------------------------+----------------------------------+
| Variable_name | Value                            | +--------------------------+----------------------------------+ | character_set_client     | latin1 |
| character_set_connection | latin1                           | | character_set_database   | utf8mb4 |
| character_set_filesystem | binary                           | | character_set_results    | latin1 |
| character_set_server | utf8mb4                          | | character_set_system     | utf8 |
| character_sets_dir | /usr/local/mysql/share/charsets/ | +--------------------------+----------------------------------+ 8 rows in set (0.06 sec) # 字符集utf8mb4 char 20 就是 80,若是有null 則null 佔一個字節,若是是varchar 則須要1-2個字節存儲值的長度 mysql> alter table test_kl add column name1 char(20) ; Query OK, 0 rows affected (0.06 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> alter table test_kl add index name_name1_index (name,name1) ; Query OK, 0 rows affected (0.02 sec) Records: 0 Duplicates: 0 Warnings: 0 mysql> explain select * from test_kl where name1 = '' ; +----+-------------+---------+------------+-------+---------------+------------------+---------+------+------+----------+--------------------------+ | id | select_type | table   | partitions | type  | possible_keys | key              | key_len | ref  | rows | filtered | Extra |
+----+-------------+---------+------------+-------+---------------+------------------+---------+------+------+----------+--------------------------+
| 1 | SIMPLE      | test_kl | NULL       | index | NULL          | name_name1_index | 161     | NULL |    1 | 100.00 | Using where; Using index | +----+-------------+---------+------------+-------+---------------+------------------+---------+------+------+----------+--------------------------+ 1 row in set, 1 warning (0.00 sec) mysql> explain select * from test_kl where name = '' -> -> ; +----+-------------+---------+------------+------+-----------------------------+------------+---------+-------+------+----------+-------+ | id | select_type | table   | partitions | type | possible_keys | key        | key_len | ref   | rows | filtered | Extra |
+----+-------------+---------+------------+------+-----------------------------+------------+---------+-------+------+----------+-------+
| 1 | SIMPLE      | test_kl | NULL       | ref | index_name,name_name1_index | index_name | 80      | const |    1 | 100.00 | NULL  | +----+-------------+---------+------------+------+-----------------------------+------------+---------+-------+------+----------+-------+ 1 row in set, 1 warning (0.00 sec) mysql> explain select * from myTest where b=3 and c=4; +----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+-------------+ | id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+-------------+
| 1 | SIMPLE      | myTest | NULL       | ALL | NULL          | NULL | NULL    | NULL | 32893 | 1.00 | Using where | +----+-------------+--------+------------+------+---------------+------+---------+------+-------+----------+-------------+ 1 row in set, 1 warning (0.00 sec) mysql> explain select * from myTest where a=3 and c=4; +----+-------------+--------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+ | id | select_type | table  | partitions | type | possible_keys | key  | key_len | ref   | rows | filtered | Extra |
+----+-------------+--------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+
| 1 | SIMPLE      | myTest | NULL       | ref | a             | a | 5       | const |    1 | 10.00 | Using index condition | +----+-------------+--------+------------+------+---------------+------+---------+-------+------+----------+-----------------------+ 1 row in set, 1 warning (0.01 sec) 複製代碼
  • ref 指明當前表所 參照的 字段。
mysql> alter table course  add index tid_index (tid) ;
Query OK, 0 rows affected (0.03 sec)
Records: 0  Duplicates: 0  Warnings: 0

mysql> explain select * from course c,teacher t where c.tid = t.tid  and t.tname ='tw' ;
+----+-------------+-------+------------+------+---------------+-----------+---------+------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra       | +----+-------------+-------+------------+------+---------------+-----------+---------+------------+------+----------+-------------+ |  1 | SIMPLE | t     | NULL | ALL  | tid_index | NULL      | NULL | NULL       | 3 |    33.33 | Using where |
| 1 | SIMPLE      | c | NULL       | ref | tid_index     | tid_index | 5       | test.t.tid |    1 | 100.00 | NULL        | +----+-------------+-------+------------+------+---------------+-----------+---------+------------+------+----------+-------------+ 複製代碼
  • rows: 被索引優化查詢的 數據個數 (實際經過索引而查詢到的 數據個數)
mysql> explain select * from course c,teacher t  where c.tid = t.tid
    -> and t.tname = 'tz' ;
+----+-------------+-------+------------+------+---------------+-----------+---------+------------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra       | +----+-------------+-------+------------+------+---------------+-----------+---------+------------+------+----------+-------------+ |  1 | SIMPLE | t     | NULL | ALL  | tid_index | NULL      | NULL | NULL       | 3 |    33.33 | Using where |
| 1 | SIMPLE      | c | NULL       | ref | tid_index     | tid_index | 5       | test.t.tid |    1 | 100.00 | NULL        | +----+-------------+-------+------------+------+---------------+-----------+---------+------------+------+----------+-------------+ 2 rows in set, 1 warning (0.00 sec) 複製代碼
  • Extra:

using filesort : 性能消耗大;須要「額外」的一次排序(查詢) 。常見於 order by 語句中。 對於單索引, 若是排序和查找是同一個字段,則不會出現using filesort;若是排序和查找不是同一個字段,則會出現using filesort; 怎麼避免: where哪些字段,就order by那些字段 where和order by 按照複合索引的順序使用,不要跨列或無序使用。數據庫

mysql> create table test02
    -> (
    -> a1 char(3),
    -> a2 char(3),
    -> a3 char(3),
    -> index idx_a1(a1),
    -> index idx_a2(a2),
    -> index idx_a3(a3)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql>
mysql> explain select * from test02 where a1 ='' order by a1 ;
+----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra | +----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+ |  1 | SIMPLE | test02 | NULL | ref  | idx_a1 | idx_a1 | 13 | const | 1 |   100.00 | NULL |
+----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+-------+
1 row in set, 1 warning (0.01 sec)

mysql> explain select * from test02 where a1 ='' order by a2 ;
+----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+---------------------------------------+
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra                                 | +----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+---------------------------------------+ |  1 | SIMPLE | test02 | NULL | ref  | idx_a1 | idx_a1 | 13 | const | 1 |   100.00 | Using index condition; Using filesort |
+----+-------------+--------+------------+------+---------------+--------+---------+-------+------+----------+---------------------------------------+
1 row in set, 1 warning (0.00 sec)
複製代碼
  • using temporary:性能損耗大 ,用到了臨時表。通常出如今group by 語句中。

避免:查詢那些列,就根據那些列 group by .

  • using index :性能提高; 索引覆蓋(覆蓋索引)。緣由:不讀取原文件,只從索引文件中獲取數據 (不須要回表查詢),只要使用到的列 所有都在索引中,就是索引覆蓋using index
  • using where (須要回表查詢)
  • impossible where : where子句永遠爲false select * from test02 where a1='x' and a1='y'

關於數據表格式規範

談談mysql中utf8和utf8mb4區別

  • 簡介

MySQL在5.5.3以後增長了這個utf8mb4的編碼,mb4就是most bytes 4的意思,專門用來兼容四字節的unicode。好在utf8mb4是utf8的超集,除了將編碼改成utf8mb4外不須要作其餘轉換。固然,爲了節省空間,通常狀況下使用utf8也就夠了。

那上面說了既然utf8可以存下大部分中文漢字,那爲何還要使用utf8mb4呢? 原來mysql支持的 utf8 編碼最大字符長度爲 3 字節,若是遇到 4 字節的寬字符就會插入異常了。三個字節的 UTF-8 最大能編碼的 Unicode 字符是 0xffff,也就是 Unicode 中的基本多文種平面(BMP)。也就是說,任何不在基本多文本平面的 Unicode字符,都沒法使用 Mysql 的 utf8 字符集存儲。包括 Emoji 表情(Emoji 是一種特殊的 Unicode 編碼,常見於 ios 和 android 手機上 ),和不少不經常使用的漢字,以及任何新增的 Unicode 字符等等。

mysql的這些坑你踩過嗎?快來看看怎麼優化mysql?

 

mysql的這些坑你踩過嗎?快來看看怎麼優化mysql?

 

- 我認爲 合理表應該這樣設計
CREATE TABLE `demo`  (
                         `id` int(11) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '主鍵Id',
                         `uuid` varchar(12) CHARACTER SET utf8 COLLATE utf8_general_ci NOT NULL COMMENT '業務id',
                         `create_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) COMMENT '建立時間',
                         `update_time` timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6) COMMENT '更新時間',
                         `status` tinyint(2) NOT NULL DEFAULT 0 COMMENT '狀態 0:正常 1:下線',
                         `logical_del` tinyint(2) NOT NULL DEFAULT 0 COMMENT '邏輯刪除標識',
                         PRIMARY KEY `id`(`Id`) USING BTREE,
                         INDEX `uuid`(`uuid`) USING BTREE

) ENGINE = InnoDB  CHARSET=utf8mb4  COMMENT = 'demo';

最後,小編還給你們整理了-份面試題庫,有須要的添加小編的vx: mxzFAFAFA便可免費領取! ! !

相關文章
相關標籤/搜索