python Mysql (二)

MySQL核心特性详解
本文深入讲解MySQL中的事务、视图、触发器、函数、存储过程等高级特性,并介绍索引的种类及其应用技巧,帮助读者掌握高效管理和优化MySQL数据库的方法。

Mysql (二)

一. 事务

a.数据库开启事务命令  

1
2
3
4
#start transaction 开启事务
#Rollback 回滚事务,即撤销指定的sql语句(只能回退insert delete update语句),回滚到上一次commit的位置
#Commit 提交事务,提交未存储的事务
#savepoint 保留点 ,事务处理中设置的临时占位符 你可以对它发布回退(与整个事务回退不同)
 1 create table account(
 2     id int,
 3     name varchar(32),
 4     balance double);
 5 
 6 insert into account values(1,"alex",8000);
 7 insert into account values(2,"egon",2000);
 8 
 9 
10 
11 #方式一: 更改数据后回滚,数据回到原来
12 
13 select * from account;
14     +------+------+---------+
15     | id   | name | balance |
16     +------+------+---------+
17     |    1 | alex |    8000 |
18     |    2 | egon |    2000 |
19     +------+------+---------+
20 
21 start transaction;      #开启事务后,更改数据发现数据变化
22 
23 update account set balance=balance-1000 where id=1;   #alex减去1000
24 select * from account;
25     +------+------+---------+
26     | id   | name | balance |
27     +------+------+---------+
28     |    1 | alex |    7000 |
29     |    2 | egon |    2000 |
30     +------+------+---------+
31 
32 
33 rollback;               #回滚后,发现数据回到原来
34 
35 select * from account;
36     +------+------+---------+
37     | id   | name | balance |
38     +------+------+---------+
39     |    1 | alex |    8000 |
40     |    1 | egon |    2000 |
41     +------+------+---------+
42 
43 
44 #方式二: 更改数据后提交
45 
46 select * from account;
47     +------+------+---------+
48     | id   | name | balance |
49     +------+------+---------+
50     |    1 | alex |    8000 |
51     |    2 | egon |    2000 |
52     +------+------+---------+
53 
54 update account set balance=balance-1000 where id=1;
55 pdate account set balance=balance+1000 where id=2;
56 Commit;
57 
58  select * from account;
59     +------+------+---------+
60     | id   | name | balance |
61     +------+------+---------+
62     |    1 | alex |    7000 |
63     |    2 | egon |    3000 |
64     +------+------+---------+
数据库 事务操作演示
 1 import pymysql
 2 
 3 #添加数据
 4 
 5 conn = pymysql.connect(host='10.37.129.3', port=3306, user='egon', passwd='123456', db='wuSir',charset="utf8")
 6 
 7 cursor = conn.cursor()
 8 
 9 
10 try:
11     insertSQL0="INSERT INTO account (name,balance) VALUES ('oldboy',4000)"
12     insertSQL1="UPDATE account set balance=balance-1000 WHERE id=1"
13     insertSQL2="UPDATE account set balance=balance+1000 WHERE id=2"
14 
15     cursor = conn.cursor()
16 
17     cursor.execute(insertSQL0)
18     conn.commit()                   
19 
20 
21     #主动触发Exception,事务回滚,回滚到上面conn.commit() 
22     cursor.execute(insertSQL1)
23     raise Exception
24     cursor.execute(insertSQL2)
25     cursor.close()
26     conn.commit()
27 
28 except Exception as e:
29 
30     conn.rollback()
31     conn.commit()
32 
33 
34 cursor.close()
35 conn.close()
python中调用数据库启动事务

 

二. 视图 

视图是一个虚拟表(非真实存在),其本质是【根据SQL语句获取动态的数据集,并为其命名】,用户使用时只需使用【名称】即可获取结果集,并可以将其当作表来使用。

a. 创建视图

1
2
3
4
5
6
7
#格式:CREATE VIEW 视图名称 AS  SQL语句
  
#演示
create view v1 as select  *  from  student where sid >  10 ;
 
#下次调用
select  *  from  v1;

b. 删除视图

1
2
3
4
#格式:DROP VIEW 视图名称
 
#演示
drop view v1;

c. 修改视图

1
2
3
4
#格式:ALTER VIEW 视图名称 AS SQL语句
 
#演示
alter view v1 as select  *  from  student where sid >  13 ;

三. 触发器

对某个表进行【增/删/改】操作的前后如果希望触发某个特定的行为时,可以使用触发器,触发器用于定制用户对表的行进行【增/删/改】前后的行为。

特别的:NEW表示即将插入的数据行,OLD表示即将删除的数据行。

a. 创建基本语法

 1 # 插入前
 2 CREATE TRIGGER tri_before_insert_tb1 BEFORE INSERT ON tb1 FOR EACH ROW
 3 BEGIN
 4     ...
 5 END
 6 
 7 # 插入后
 8 CREATE TRIGGER tri_after_insert_tb1 AFTER INSERT ON tb1 FOR EACH ROW
 9 BEGIN
10     ...
11 END
12 
13 # 删除前
14 CREATE TRIGGER tri_before_delete_tb1 BEFORE DELETE ON tb1 FOR EACH ROW
15 BEGIN
16     ...
17 END
18 
19 # 删除后
20 CREATE TRIGGER tri_after_delete_tb1 AFTER DELETE ON tb1 FOR EACH ROW
21 BEGIN
22     ...
23 END
24 
25 # 更新前
26 CREATE TRIGGER tri_before_update_tb1 BEFORE UPDATE ON tb1 FOR EACH ROW
27 BEGIN
28     ...
29 END
30 
31 # 更新后
32 CREATE TRIGGER tri_after_update_tb1 AFTER UPDATE ON tb1 FOR EACH ROW
33 BEGIN
34     ...
35 END
View Code
 1 #----------------------示例一:
 2 
 3 #创建触发器
 4 
 5 delimiter //
 6 create trigger t2 before insert on student for each row
 7 BEGIN
 8 insert into teacher(tname) values("张三");
 9 END //
10 delimiter ;
11 
12 
13 #student插入数据,查看teacher表中是否有数据
14 
15 insert into student(gender,class_id,sname) values("",3,"王五");
16 
17 
18 #删除触发器
19 
20 drop trigger t2;
21 
22 
23 
24 #----------------------示例二
25 
26 #重新创建  new   
27 
28 delimiter //
29 create trigger t2 before insert on student for each row
30 BEGIN
31 insert into teacher(tname) values(NEW.sname);
32 END //
33 delimiter ;
34 
35 #创建的触发的name 相同
36 insert into student(gender,class_id,sname) values("",3,"李五");
触发器 演示

四. 函数 

 1 CHAR_LENGTH(str)
 2         返回值为字符串str 的长度,长度的单位为字符。一个多字节字符算作一个单字符。
 3         对于一个包含五个二字节字符集, LENGTH()返回值为 10, 而CHAR_LENGTH()的返回值为5。
 4 
 5     CONCAT(str1,str2,...)
 6         字符串拼接
 7         如有任何一个参数为NULL ,则返回值为 NULL。
 8     CONCAT_WS(separator,str1,str2,...)
 9         字符串拼接(自定义连接符)
10         CONCAT_WS()不会忽略任何空字符串。 (然而会忽略所有的 NULL)。
11 
12     CONV(N,from_base,to_base)
13         进制转换
14         例如:
15             SELECT CONV('a',16,2); 表示将 a 由16进制转换为2进制字符串表示
16 
17     FORMAT(X,D)
18         将数字X 的格式写为'#,###,###.##',以四舍五入的方式保留小数点后 D 位, 并将结果以字符串的形式返回。若  D 为 0, 则返回结果不带有小数点,或不含小数部分。
19         例如:
20             SELECT FORMAT(12332.1,4); 结果为: '12,332.1000'
21     INSERT(str,pos,len,newstr)
22         在str的指定位置插入字符串
23             pos:要替换位置其实位置
24             len:替换的长度
25             newstr:新字符串
26         特别的:
27             如果pos超过原字符串长度,则返回原字符串
28             如果len超过原字符串长度,则由新字符串完全替换
29     INSTR(str,substr)
30         返回字符串 str 中子字符串的第一个出现位置。
31 
32     LEFT(str,len)
33         返回字符串str 从开始的len位置的子序列字符。
34 
35     LOWER(str)
36         变小写
37 
38     UPPER(str)
39         变大写
40 
41     LTRIM(str)
42         返回字符串 str ,其引导空格字符被删除。
43     RTRIM(str)
44         返回字符串 str ,结尾空格字符被删去。
45     SUBSTRING(str,pos,len)
46         获取字符串子序列
47 
48     LOCATE(substr,str,pos)
49         获取子序列索引位置
50 
51     REPEAT(str,count)
52         返回一个由重复的字符串str 组成的字符串,字符串str的数目等于count 。
53         若 count <= 0,则返回一个空字符串。
54         若str 或 count 为 NULL,则返回 NULL 。
55     REPLACE(str,from_str,to_str)
56         返回字符串str 以及所有被字符串to_str替代的字符串from_str 。
57     REVERSE(str)
58         返回字符串 str ,顺序和字符顺序相反。
59     RIGHT(str,len)
60         从字符串str 开始,返回从后边开始len个字符组成的子序列
61 
62     SPACE(N)
63         返回一个由N空格组成的字符串。
64 
65     SUBSTRING(str,pos) , SUBSTRING(str FROM pos) SUBSTRING(str,pos,len) , SUBSTRING(str FROM pos FOR len)
66         不带有len 参数的格式从字符串str返回一个子字符串,起始于位置 pos。带有len参数的格式从字符串str返回一个长度同len字符相同的子字符串,起始于位置 pos。 使用 FROM的格式为标准 SQL 语法。也可能对pos使用一个负值。假若这样,则子字符串的位置起始于字符串结尾的pos 字符,而不是字符串的开头位置。在以下格式的函数中可以对pos 使用一个负值。
67 
68         mysql> SELECT SUBSTRING('Quadratically',5);
69             -> 'ratically'
70 
71         mysql> SELECT SUBSTRING('foobarbar' FROM 4);
72             -> 'barbar'
73 
74         mysql> SELECT SUBSTRING('Quadratically',5,6);
75             -> 'ratica'
76 
77         mysql> SELECT SUBSTRING('Sakila', -3);
78             -> 'ila'
79 
80         mysql> SELECT SUBSTRING('Sakila', -5, 3);
81             -> 'aki'
82 
83         mysql> SELECT SUBSTRING('Sakila' FROM -4 FOR 2);
84             -> 'ki'
85 
86     TRIM([{BOTH | LEADING | TRAILING} [remstr] FROM] str) TRIM(remstr FROM] str)
87         返回字符串 str , 其中所有remstr 前缀和/或后缀都已被删除。若分类符BOTH、LEADIN或TRAILING中没有一个是给定的,则假设为BOTH 。 remstr 为可选项,在未指定情况下,可删除空格。
88 
89         mysql> SELECT TRIM('  bar   ');
90                 -> 'bar'
91 
92         mysql> SELECT TRIM(LEADING 'x' FROM 'xxxbarxxx');
93                 -> 'barxxx'
94 
95         mysql> SELECT TRIM(BOTH 'x' FROM 'xxxbarxxx');
96                 -> 'bar'
97 
98         mysql> SELECT TRIM(TRAILING 'xyz' FROM 'barxxyz');
99                 -> 'barx'
部分内置函数

  官方内置函数 

a. 显示时间月份

1
2
3
4
select DATE_FORMAT(ctime,  "%Y-%m" ),count( 1 from  blog group DATE_FORMAT(ctime,  "%Y-%m" )
 
2019 - 11    2
2019 - 10    2

b. 自定义函数

 1 #自定义函数
 2 
 3 delimiter //
 4 create function f1(
 5     i1 int,
 6     i2 int)
 7 returns int
 8 BEGIN
 9     declare num int;
10     set num = i1 + i2;
11     return(num);
12 END //
13 delimiter ;
14 
15 
16 #执行函数
17 
18 select f1(1,99);
19 +----------+
20 | f1(1,99) |
21 +----------+
22 |      100 |
23 +----------+
View Code

 

c. 删除函数

1
#drop function func_name;

d. 执行函数

1 # 获取返回值
2 declare @i VARCHAR(32);
3 select UPPER('alex') into @i;
4 SELECT @i;
5 
6 
7 # 在查询中使用
8 select f1(11,nid) ,name from tb2;
View Code

 

五. 存储过程

 存储过程是一个SQL语句集合,当主动去调用存储过程时,其中内部的SQL语句会按照逻辑执行。

a. 创建存储过程

 1 #定义存储过程
 2 
 3 delimiter //
 4 create procedure p1()
 5 BEGIN
 6   select * from student;
 7   insert into teacher(tname) values("alex");
 8 END //
 9 delimiter ;
10 
11 
12 
13 #调用
14 
15 call p1();
无参数存储过程 演示
 1 import pymysql
 2 
 3 
 4 conn = pymysql.connect(host='10.37.129.3', port=3306, user='egon', passwd='123456', db='wuSir',charset="utf8")
 5 
 6 cursor = conn.cursor()
 7 
 8 cursor.callproc("p1")
 9 
10 conn.commit()
11 
12 result = cursor.fetchall()
13 print(result)
14 
15 
16 cursor.close()
17 conn.close()
pymysql 调用存储过程

 

b. 有参数存储过程

  对于存储过程,可以接收参数,其参数有三类:

  • in          仅用于传入参数用
  • out        仅用于返回值用
  • inout     既可以传入又可以当作返回值
 1 delimiter //
 2 create procedure p3(
 3     in n1 int,
 4     out n2 int
 5 )
 6 BEGIN
 7     set n2 = 123;
 8     select * from student where sid > n1;
 9 END //
10 delimiter ;
11 
12 
13 set @v1= 0;
14 select @v1;
15 
16 #调用 发现@v1的值发生变化
17 call p3(12,@v1);
18 select @v1;
有参数存储过程演示
 1 #----------mysql 代码
 2 
 3 delimiter //
 4 create procedure p4(
 5     in n1 int,
 6     out n2 int
 7 )
 8 BEGIN
 9     set n2 = 123;
10     select * from student where sid > n1;
11 END //
12 delimiter ;
13 
14 set @_p3_0 = 12;
15 set @_p3_1 = 2;
16 
17 
18 #调用 发现@v1的值发生变化
19 call p3(@_p3_0,@_p3_1);
20 
21 select @_p3_0;
22 select @_p3_1;
23 
24 
25 
26 #--------pymysql--------
27 
28 import pymysql
29 
30 
31 conn = pymysql.connect(host='10.37.129.3', port=3306, user='egon', passwd='123456', db='wuSir',charset="utf8")
32 cursor = conn.cursor()
33 
34 
35 #获取结果集
36 cursor.callproc("p3",(13,2))     #相当于mysql set定义的两个变量和call执行
37 
38 
39 #找出in out 的参数值
40 
41 cursor.execute("select @_p3_0,@_p3_1")
42 r2 = cursor.fetchall()
43 print(r2)
44 
45 
46 cursor.close()
47 conn.close()
pymysql 操作有参数的存储过程

c. 事务

 1 delimiter \\
 2                         create PROCEDURE p1(
 3                             OUT p_return_code tinyint
 4                         )
 5                         BEGIN 
 6                           DECLARE exit handler for sqlexception 
 7                           BEGIN 
 8                             -- ERROR 
 9                             set p_return_code = 1; 
10                             rollback; 
11                           END; 
12                          
13                           DECLARE exit handler for sqlwarning 
14                           BEGIN 
15                             -- WARNING 
16                             set p_return_code = 2; 
17                             rollback; 
18                           END; 
19                          
20                           START TRANSACTION; 
21                             DELETE from tb1;
22                             insert into tb2(name)values('seven');
23                           COMMIT; 
24                          
25                           -- SUCCESS 
26                           set p_return_code = 0; 
27                          
28                           END\\
29                     delimiter ;
事务 演示

d. 游标

 1 #  创建A,B表  把A表数据插入B表
 2 
 3 create table A(
 4     id int,
 5     num int
 6     )engine=innodb default charset=utf8;
 7 
 8 create table B(
 9     id int not null auto_increment primary key,
10     num int
11     )engine=innodb default charset=utf8;
12 
13 insert into A(id,num) values(1,100),(2,200),(3,300);
14 
15 
16 
17 # 创建游标
18 
19 delimiter //
20 create procedure p9()
21 begin
22     declare row_id int;
23     declare row_num int;
24     declare done INT DEFAULT FALSE;
25     declare temp int;
26 
27     declare my_cursor CURSOR FOR select id,num from A;
28     declare CONTINUE HANDLER FOR NOT FOUND SET done = TRUE;
29 
30     open my_cursor;
31         xxoo: LOOP
32             fetch my_cursor into row_id,row_num;
33             if done then
34                 leave xxoo;
35             END IF;
36             set temp = row_id + row_num;
37             insert into B(num) values(temp);
38         end loop xxoo;
39     close my_cursor;
40 
41 end  //
42 delimiter ;
43 
44 
45 
46 #执行 检查
47 
48 call p9();
49 select * from B;
游标 案例演示

e. 动态执行SQL 

 1 delimiter \\
 2     CREATE PROCEDURE p8 (
 3         in nid int
 4     )
 5     BEGIN
 6         set @nid = nid;
 7         PREPARE prod FROM 'select * from student where sid > ?';
 8         EXECUTE prod USING @nid;
 9         DEALLOCATE prepare prod; 
10     END\\
11     delimiter ;
View Code

 

六. 索引

MySQL中常见索引有: 

  • 普通索引:  加速查询
  • 唯一索引:      加速查询 + 列值唯一  + (可以有null)
  • 主键索引:      加速查询 + 列值唯一  + 表中只有一个(不可以有null)
  • 组合索引:      多列值组成一个索引,专门用于组合搜索,其效率大于索引合并
  • 全文索引:      对文本的内容进行分词,进行搜索 

索引合并,使用多个单列索引组合搜索
覆盖索引,select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖 

a. 普通索引

普通索引仅有一个功能:加速查询

1 create table in1(
2     nid int not null auto_increment primary key,
3     name varchar(32) not null,
4     email varchar(64) not null,
5     extra text,
6     index ix_name (name)
7 )
创建表 + 索引
 1 #创建索引
 2 create index index_name on table_name(column_name);
 3 
 4 #注意:对于创建索引时如果是BLOB 和 TEXT 类型,必须指定length。
 5 create index ix_extra on in1(extra(32));
 6 
 7 
 8 #删除索引
 9 drop index_name on table_name;
10 
11 #查看索引
12 show index from table_name;
普通索引 演示

b. 唯一索引

唯一索引有两个功能:加速查询 和 唯一约束(可含null)

 1 #创建表时建索引
 2 create table in1(
 3     nid int not null auto_increment primary key,
 4     name varchar(32) not null,
 5     email varchar(64) not null,
 6     extra text,
 7     unique ix_name (name)
 8 )
 9 
10 
11 #追加索引
12 create unique index 索引名 on 表名(列名);
13 
14 
15 #删除索引
16 drop unique index 索引名 on 表名
唯一索引 演示

c. 主键索引

主键有两个功能:加速查询 和 唯一约束(不可含null)

 1 #创建索引
 2 
 3 create table in1(
 4     nid int not null auto_increment primary key,
 5     name varchar(32) not null,
 6     email varchar(64) not null,
 7     extra text
 8 )
 9 
10 OR
11 
12 create table in1(
13     nid int not null auto_increment,
14     name varchar(32) not null,
15     email varchar(64) not null,
16     extra text,
17     primary key(ni1)
18 )
19 
20 
21 #追加主键
22 alter table 表名 add primary key(列名);
23 
24 #删除主键
25 alter table 表名 drop primary key;
26 alter table 表名  modify  列名 int, drop primary key;
主键 演示

d. 组合索引

组合索引是将n个列组合成一个索引

其应用场景为:频繁的同时使用n列来进行查询,如:where n1 = 'alex' and n2 = 666。

 1 create table in3(
 2     nid int not null auto_increment primary key,
 3     name varchar(32) not null,
 4     email varchar(64) not null,
 5     extra text
 6 )
 7 
 8 #创建组合索引
 9 create index ix_name_email on in3(name,email);
10 
11 
12 
13 #-----------------
14 #如上创建组合索引之后,查询:
15 
16 name and email  -- 使用索引
17 name                 -- 使用索引
18 email                 -- 不使用索引
19 #注意:对于同时搜索n个条件时,组合索引的性能好于多个单一索引合并。
组合索引 演示

七. 分页 

 1  1. 页面只有上一页,下一页
 2         # max_id
 3         # min_id
 4         下一页:
 5             select * from userinfo3 where id > max_id limit 10;
 6         上一页:
 7             select * from userinfo3 where id < min_id order by id desc limit 10;
 8             
 9     2. 上一页 192 193  [196]  197  198  199 下一页
10         
11         select * from userinfo3 where id in (
12             select id from (select id from userinfo3 where id > max_id limit 30) as N order by N.id desc limit 10
13         )
分页方案

八. 执行计划

explain + 查询SQL - 用于显示SQL执行信息参数,根据参考信息可以进行SQL优化 

1
2
3
4
5
6
7
mysql> explain select  *  from  tb2;
+ - - - - + - - - - - - - - - - - - - + - - - - - - - + - - - - - - + - - - - - - - - - - - - - - - + - - - - - - + - - - - - - - - - + - - - - - - + - - - - - - + - - - - - - - +
id  | select_type | table |  type  | possible_keys | key  | key_len | ref  | rows | Extra |
+ - - - - + - - - - - - - - - - - - - + - - - - - - - + - - - - - - + - - - - - - - - - - - - - - - + - - - - - - + - - - - - - - - - + - - - - - - + - - - - - - + - - - - - - - +
|   1  | SIMPLE      | tb2   |  ALL   | NULL          | NULL | NULL    | NULL |     2  | NULL  |
+ - - - - + - - - - - - - - - - - - - + - - - - - - - + - - - - - - + - - - - - - - - - - - - - - - + - - - - - - + - - - - - - - - - + - - - - - - + - - - - - - + - - - - - - - +
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 = 'seven@live.com'
32                                    select * from tb1 where email = 'seven@live.com' 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列中索引的位图,并且是冗余的。
View Code

 

九. 其它注意事项

1
2
3
4
5
6
7
8
9
-  避免使用select  *
-  count( 1 )或count(列) 代替 count( * )
-  创建表时尽量时 char 代替 varchar
-  表的字段顺序固定长度的字段优先
-  组合索引代替多个单列索引(经常使用多个条件查询时)
-  尽量使用短索引
-  使用连接(JOIN)来代替子查询(Sub - Queries)
-  连表时注意条件类型需一致
-  索引散列值(重复少)不适合建索引,例:性别不适合

十. 下列不走索引

- like '%xx'
    select * from tb1 where name like '%cn';
- 使用函数
    select * from tb1 where reverse(name) = 'wupeiqi';
- or
    select * from tb1 where nid = 1 or email = 'seven@live.com';
    特别的:当or条件中有未建立索引的列才失效,以下会走索引
            select * from tb1 where nid = 1 or name = 'seven';
            select * from tb1 where nid = 1 or email = 'seven@live.com' and name = 'alex'
- 类型不一致
    如果列是字符串类型,传入条件是必须用引号引起来,不然...
    select * from tb1 where name = 999;
- !=
    select * from tb1 where name != 'alex'
    特别的:如果是主键,则还是会走索引
        select * from tb1 where nid != 123
- >
    select * from tb1 where name > 'alex'
    特别的:如果是主键或索引是整数类型,则还是会走索引
        select * from tb1 where nid > 123
        select * from tb1 where num > 123
- order by
    select email from tb1 order by name desc;
    当根据索引排序时候,选择的映射如果不是索引,则不走索引
    特别的:如果对主键排序,则还是走索引:
        select * from tb1 order by nid desc;
  
- 组合索引最左前缀
    如果组合索引为:(name,email)
    name and email       -- 使用索引
    name                 -- 使用索引
    email                -- 不使用索引

  

MySQL(一)

MySQL(二)

MySQL(三)

MySQL(四)

 wuSir   wuSir

转载于:https://www.cnblogs.com/guobaoyuan/p/7087702.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值