MySQL笔记
SQL分类:
DDL:数据定义语言,这些语句定义了不同的数据段、数据库、表、列、索引等数据库对象的定义,常用的语句关键字包括create、drop、alter、等
DML:数据操控语句,用于添加、删除、更新和查询数据库语句,并检查数据完整性,常用的语句关键字主要包括insert、delete、update和select。
DCL:数据控制语句,用于控制不同数据段直接的许可和访问级别的语句,这些语句定义了数据库、表、字段、用户的访问权限和安全级别。主要的语句关键字包括grant、revoke。
登录数据库:mysql -uroot -hlocalhost -p 创建数据库:create database test1 查看数据库:show databases 选择数据库:use dbname 查看数据库中的表:show tables 删除数据库:drop database dbname 删除表,定义和数据:drop table tablename 删除表全部数据:Truncate table tablename 删除表部分数据,带where:Delete From tablename Where 列名称=值
查看表的定义:show create table emp \G
修改表:先删除再创建
修改表类型:alter table tablename modify column 字段定义 [first | after 字段名] 增加表字段:alter table tablename add column 字段定义 [first | after 字段名] 删除表字段:alter table tablename drop column 字段名 字段改名:alter table tablename change column 旧字段名 字段定义 [first | after 字段名] 修改字段排列顺序:[first | after 字段名]这个选项可以用来修改字段在表中的位置,add增加的新字段是加在表的最后位置,而modify和change默认不改变位置。 表改名:alter table tablename rename to 新表名
修改存储引擎(可以在创建表的时候指定);alter table tablename engine = innodb;
DML:having可以对聚合后的结果进行条件的过滤,可用聚合函数,而where是在聚合前就对记录进行过滤,如果逻辑允许,我们尽可能用where先过滤记录。
插入记录:insert into tablename (字段名1,字段名2,....) values (value1,value2,...),(value1,value2,...),(value1,value2,...)....;
更新记录:update tablename set field1 = value1,field2 = value2 ... [where ...]
删除记录:delete from tablename [where ...]
select [distinct]
from tablename
[where ]
[group by]
[having ]
[order by [ASC | DESC]]
[limit offset_start(记录的起始偏移量),row_count(表示的行数)]
CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name (create_definition,...) [table_options] [partition_options]
DCL:
创建一个数据库用户z1,具有对sakila数据库中所有表的select、insert权限 grant select,insert on sakila.* to 'z1'@'localhost' identified by '123'; 将z1的权限变更,收回insert,只能对数据进行insert操作 revoke insert on sakila.* from 'z1'@'localhost';
数值类型:
decimal:以字符串形式存放,比浮点数更精确。M表示一共有M个数字,D表示位于小数点后的位数,
类型 | 大小 | 范围(有符号) | 范围(无符号) |
---|---|---|---|
TINYINT | 1 字节 | (-128,127) | (0,255) |
SMALLINT | 2 字节 | (-32 768,32 767) | (0,65 535) |
MEDIUMINT | 3 字节 | (-8 388 608,8 388 607) | (0,16 777 215) |
INT或INTEGER | 4 字节 | (-2 147 483 648,2 147 483 647) | (0,4 294 967 295) |
BIGINT | 8 字节 | (-9,223,372,036,854,775,808,9 223 372 036 854 775 807) | (0,18 446 744 073 709 551 615) |
FLOAT | 4 字节 | (-3.402 823 466 E+38,-1.175 494 351 E-38),0,(1.175 494 351 E-38,3.402 823 466 351 E+38) | 0,(1.175 494 351 E-38,3.402 823 466 E+38) |
DOUBLE | 8 字节 | (-1.797 693 134 862 315 7 E+308,-2.225 073 858 507 201 4 E-308),0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) | 0,(2.225 073 858 507 201 4 E-308,1.797 693 134 862 315 7 E+308) |
DECIMAL | M+2 | 依赖于M和D的值 | 依赖于M和D的值 |
日期和时间:
类型 | 大小 (字节) | 范围 | 格式 |
---|---|---|---|
DATE | 3 | 1000-01-01/9999-12-31 | YYYY-MM-DD |
TIME | 3 | '-838:59:59'/'838:59:59' | HH:MM:SS |
YEAR | 1 | 1901/2155 | YYYY |
DATETIME | 8 | 1000-01-01 00:00:00/9999-12-31 23:59:59 | YYYY-MM-DD HH:MM:SS |
TIMESTAMP | 4 |
1970-01-01 00:00:00/2038 结束时间是第 2147483647 秒,北京时间 2038-1-19 11:14:07,格林尼治时间 2038年1月19日 凌晨 03:14:07 |
YYYYMMDD HHMMSS |
字符串类型:
char:长度固定为创建表时声明的长度。会删除尾部的空格。
varchar:可变长字符串,保留尾部的空格。
enum:枚举类型,1~255个成员的枚举需要1个字节存储,255~65536个成员需要2个字节存储。不区分大小写,对于超出范围的则没有值,枚举值会与一个整数映射。所以也可以插入一个整数。
set:1~8个成员的集合,占一个字节;9~16个成员集合,占2个字节;17~24个成员集合,占3个字节。
如果有8个成员:10000000,表示第一个成员,01000000表示第二成员......
类型 | 大小 | 用途 |
---|---|---|
CHAR | 0-255字节 | 定长字符串 |
VARCHAR | 0-65535 字节 | 变长字符串 |
TINYBLOB | 0-255字节 | 不超过 255 个字符的二进制字符串 |
TINYTEXT | 0-255字节 | 短文本字符串 |
BLOB | 0-65 535字节 | 二进制形式的长文本数据 |
TEXT | 0-65 535字节 | 长文本数据 |
MEDIUMBLOB | 0-16 777 215字节 | 二进制形式的中等长度文本数据 |
MEDIUMTEXT | 0-16 777 215字节 | 中等长度文本数据 |
LONGBLOB | 0-4 294 967 295字节 | 二进制形式的极大文本数据 |
LONGTEXT | 0-4 294 967 295字节 | 极大文本数据 |
运算符:
between:存在于指定范围 in:存在于指定集合 is null:为NULL is not null:不为NULL like:通配符匹配 %:0或多个字符的任意字符 _:匹配一个字符 regexp:正则表达式匹配 str regexp str_pat:如果str包含str_pat则返回1
字符串函数:
cancat(s1,s2,s3...):连接s1,s2,s3...为一个字符串 insert(str,x,y,instr):将字符串str从x位置开始,y个字节长的子串替换为字符串instr lower(str):变小写 upper(str):变大写 left(str,x):返回str最左边的x个字符 right(str,x):返回str最右边的x个字符 ltrim(str):去掉str左边的空格 rtrim(str):去掉str右边的空格 trim(str):去掉俩边的空格 repeat(str,x):返回str重复x次的结果 replace(str,a,b):用字符串b替换字符串str中所有出现的字符串a strcmp(s1,s2):比较字符串s1,s2,如果这两个字符串相等返回0,如果第一个参数是根据当前的排序顺序比第二较小则返回-1,否则返回1。 substring(str,x,y):返回从字符串str x位置起y个字符长度的字符串
数值函数:
abs(x):x的绝对值 ceil(x):返回大于x的最大整数 floor(x):返回小于x的最大整数 mod(x,y):返回 x / y 的模,如果有一个是NULL则为NULL rand():返回0-1内的随机值 round(x,y):返回参数x的四舍五入的有y位小数的值,y不写默认为0 truncate(x,y):返回数字x截断(不四舍五入)为y位小数的结果
日期时间函数:
curdate():返回当前日期 curtime():返回当前时间 now():返回当前日期和时间 unix_timestamp(data):返回日期的Unix时间戳 from_unixtime(unixtime):返回Unix时间戳的日期值 week(date):返回日期是一年的第几周 year(date):返回日期的年份 hour(time):返回时间的小时值 minute(time):返回分钟值 monthname(date):返回日期的月份值 date_format(date,fmt):返回按字符串fmt格式化日期值 date_add(date,interval expr type):返回一个容器或时间值加上一个时间间隔的时间值 date_add(now(),interval 31 day) datediff(expr1,expr2):返回起始时间expr1和结束时间expr2之间的天数
MySQL存储引擎:插件式存储引擎是MySQL数据库最重要的特性之一,用户可以根据应用的需要选择如何存储和索引数据、是否使用事务等。
特点 | MyISAM | Innodb | MEMORY | MERGE | NDB |
存储限制 | 有 | 64TB | 有 | 没有 | 有 |
事务安全 | 支持 | ||||
锁机制 | 表锁 | 行锁 | 表锁 | 表锁 | 行锁 |
B树索引 | 支持 | 支持 | 支持 | 支持 | 支持 |
哈希索引 | 支持 | 支持 | |||
全文索引 | 支持 | ||||
集群索引 | 支持 | ||||
数据缓存 | 支持 | 支持 | 支持 | ||
索引缓存 | 支持 | 支持 | 支持 | 支持 | 支持 |
数据可压缩 | 支持 | ||||
空间使用 | 低 | 高 | N/A | 低 | 低 |
内存使用 | 低 | 高 | 中等 | 低 | 高 |
批量插入的速度 | 高 | 低 | 高 | 高 | 高 |
支持外键 | 支持 |
MyISAM:不支持事务和外键,其优势是访问的速度快。每一个MyISAM在磁盘上存储成3个文件,其文件名都是和表名相同,但扩展名分别是 .frm(存储表定义) .MYD(MYData,存储数据) .MYI(MYIndex,存储索引),数据文件和索引文件可以放置在不同的目录,平均分布IO,获取更快的速度。
MyISAM表支持3种不同的存储格式:
1.静态(固定长度)表:字段都是非变长字段,优点是存储非常迅速,容易缓存,出现故障容易恢复;缺点是占用的空间通常比动态表多。
2.动态表 :包含变长的字段,记录不是固定长度的,这样存储的优点是占用空间少,但是频繁的更新删除记录会产生碎片,需要定期执行optimize table语句或myisamchk -r命令来改善性能,并且出现故障的时候恢复相对比较困难。
3.压缩表:有myisampack工具创建,占非常小的空间,因为每一个记录是被单独压缩的。
Innodb:提供具有提交、回滚和崩溃恢复能力的事务安全。但是对吧MyISAM的存储引擎,Innodb写的处理效率差一些并且会占用更多的磁盘空间来保存数据和索引。
Innodb表的自动增长列可以手动输入,但是插入的值如果是空或者0,则实际插入的将是自动增长后的值。可以通过alter table tablename auto_increment = n语句强制设置自动增长列的初始值,默认从1开始、对于Innodb表,自动增长列必须是索引。如果是组合索引,也必须是组合索引的第一列。
外键约束:在创建外键的时候,要求父表必须有对于的索引,子表早创建外键的时候也会自动创建对应的索引。
在创建索引的时候,可以指定在删除、更新父表时,对子表进行相应的操作,包括restrict、cascade、set null、no action。其中restrict和no action相同,是指限制在子表有关联记录的情况下父表不能更新;cascade表示父表在更新或者删除时,更新或者删除子表对于记录。set null则表示父表在更新或者删除的时候,子表的对应字段被设置为null。
create table country( country_id smallint unsigned not null auto_increment, country varchar(50) not null, last_update timestamp not null default current_timestamp on update current_timestamp, primary key (county_id) )engine = Innodb default charset=utf8; create table city( city_id smallint unsigned not null auto_increment, city varchar(50) not null, country_id smallint unsigned not null, last_update timestamp not null default current_timestamp on update current_timestamp, primary key(city_id), key idx_fk_country_id(country_id), constraint 'idx_fk_country_id' foreign key (country_id) references country(country_id) on delete restrict on upadte cascade )engine = Innodb default charset=utf8;
Innodb存储表和索引有俩种方式:
1.使用共享表空间存储,这种方式创建的表的表结构保存在.frm文件中,数据和索引保存在innodb_data_home_dir和innodb_data_file_path定义的表空间中,可以是多个文件。
2.使用多表空间存储,这种方式创建的表的表结构仍然保存在.frm文件中,但是每一个表的数据和索引单独保存在,ibd中,如果是个分区表,则每个分区对于单独的,ibd文件,文件名是“表名+分区名”,可以在创建分区的时候指定每个分区的数据文件的位置,以此来将表的IO均匀分布在多个磁盘上。
数据类型的选择:
char和varchar:
MyISAM:建议使用固定长度的数据列代替可变长度的数据列
Innodb:建议使用varchar类型,对于Innodb数据表,内部的行存储格式没有区分固定长度和可变长度(所有数据都使用指向数据列值的头指针),因此固定长度的char不一定比varchar性能好。因而,主要的性能因素是数据行使用的存储总量。
TEXT、BLOB:保存大文本,text存储字符数据;blob存储二进制数据。
1.删除会在数据表中留下很大的“空洞”,建议用optimize table对表的碎片进行整理,优化性能。
2.可以使用合成的索引来提高大文本字段的查询性能。合成索引就是根据大文本字段的内容建立一个散列值,并把这个值存储在单独的数据列中,接下来就可以通过检索散列值找到数据行。但是这种技术只能用于精确匹配的查询(没有大于等于)。
浮点数和定点数:浮点数存在误差的问题,避免对浮点数作比较,如果有就使用in比较。
字符集:
字符集 | 是否定长 | 编码方式 | 其他说明 |
ASCII | 是 | 单字节7位编码 | 最早的奠基性字符集 |
IOS-8859-1/latinl | 是 | 单自己8位编码 | 西欧字符集,经常被用来转码 |
GB2312-80 | 是 | 双自己编码 | 最早标准,不推荐使用 |
GBK | 是 | 双自己编码 | 虽然不是国际,单支持的系统不少 |
GB18030 | 否 | 2字节或4字节编码 | 开始有一些支持,单数据库支持的还少见 |
UTF-32 | 是 | 4字节编码 | UCS-4原始编码,目前很少采用 |
UCS-2 | 是 | 2字节编码 | Window2000内部使用USC-2 |
UTF-16 | 否 | 2字节编码或4字节编码 | Java和windowXP/NT等内部采用UTF-16 |
UTF-8 | 否 | 1-4字节编码 | 互联网和UNIX/Linux广泛支持的Unicode字符集 |
选择因素:
1.满足应用支持语言的需求,如果应用要处理各种各样的文字,或者将发布到使用不同语言的国家和地区,就一个使用Unicode字符集
2.如果应用中涉及已有数据的导入,就要充分考虑数据库字符集对已有数据的兼容性。
3.如果数据库只需要支持中文,数据量很大,性能要求也很高,那就选择双字节定长编码的中文字符集,比如GBK。
4.如果数据库需要做大量的字符运算,如比较、排序等,选择定长字符集可能更好,因为定长字符集的处理速度要比变长字符集的处理速度快。
5.如果所有客户端都支持相同的字符集,应该优先选择该字符集作为数据库字符集。
MySQL服务器可以支持多种字符集,在同一台服务器、同一个数据库、甚至同一个表的不同字段都可以指定不同的字符集。
MySQL的字符集包括字符集和校对集。字符集是用来定义MySQL存储字符串的方式,校对规则是定义了比较字符串的方式,字符集和校对集是一对多的关系。校对集命名约定:它们以其相关的字符集名开始,通常包括一个语言名,并且以_ci(大小写不敏感)、_cs(大小写敏感)、_bin(二元,即比较是基于字符编码的值进行比较的)
MySQL有4种级别的默认设置:服务器级别、数据库级、表级、字段级。
服务器级别:服务器字符集和校对在MySQL服务启动时候确定。如果没有指定校对集则使用字符集的默认校对规则。
在my.cnf中设置: [mysqld] default-character-set=gbk 或者在启动选项中指定: mysql --default-character-set=gbk 或者在编译的时候指定: ./configure --with-charset=gbk
数据库级:数据库的字符集和校对规则在创建数据库的时候指定,也可以在创建完数据库后通过 alter datebase命令进行修改。如果数据库已经存在数据,因为修改字符集并不能将已有的数据按照新的字符集的字符进行存放,所以不能通过修改数据库的字符集直接修改数据的内容。如果没有指定字符集和校对规则,则使用服务器字符集和校对规则。
连接字符集和校对规则:对于客户端和服务器的交互操作,MySQL提供了3个不同的参数:character_set_client、character_set_connection、character_set_results,分别代表客户端、连接和返回结果的字符集,通常情况下,这3个字符集应该是相同的,才可以确保用户写入的数据可以正确的读取。
一次设置3个参数:set names .....;
字符集的修改:对已有数据的数据库进行字符集的修改。模拟将latin1字符集的数据库修改成GBK字符集的数据库的过程。
1.导出表结构:mysqldump -uroot -p --default-character-set=gbk -d databasename > createtab.sql
其中--default-character-set=gbk表示设置以什么字符集连接,-d表示只导出表结构,不导出数据
2.手动修改createtab.sql中表结构定义中的字符集为新的字符集,
3.确保记录不在更新,导出所有记录:mysqldump -uroot -p --quick --no-create-info --extended-insert --default-character-set=latin1 database > data.sql
--quick:用于转储大的表。它强制mysqldump从服务器一次一行地检索表中的行而不是检索所有行,并在输出前将它缓存到内存中。
--extended-insert:使用包括几个values列表的多行insert语句。这样使转储文件更小,重载文件时可以加速插入。
--no-create-info:不写重新创建每个转储表的create table语句。
--default-character-set=latin1:按照原有的字符集导出所有数据,这样导出的文件不会出现乱码
4.打开data.sql,将set names latin1修改为set names gbk
5.使用新的字符集创建新的数据库:create tablebase databasename default charset gbk
6.创建表,执行createtab,sql:mysql -uroot -p -databasename < createtab.sql
7.导入数据,执行data,sql:mysql -uroot -p -databasename < data,sql
索引的设计和使用:所有mysql列类型都可以被索引,对相关列使用索引是提高select操作性能的最佳途径。MyISAM和Innodb存储引擎的表都是默认创建BTREE索引,也支持前缀索引即对索引字段的前N个字符创建索引。前缀索引的长度更存储引擎有关,MyISAM的前缀索引可以达到1000字节长,而对于Innodb则是767字节。
创建索引
为city表的city字段创建10字节的前缀索引 create index cityname on city(city(10))
索引设计的原则:
1.搜索的索引列,不一定是所要选择的列。最适合索引的列是出现在where子句中的列,或者是连接子句指定的列,而不是出现在select关键字后的选择;列表的列
2.使用唯一索引。考虑某列中值的分布,索引的列的基数越大,索引的效果越好即重复项少。
3.使用短索引。如果对一个字符串进行索引,应该指定一个前缀长度,只要有可能就应该这样做。
4.不要过度索引。索引越多占用的磁盘空间越多,写操作的性能下降。因为要进行索引的更新。
视图:是一种虚拟存在的表,对于使用视图的用户来说基本上是透明的,视图并不在数据库中实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。
优势:
1.简单,使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的复合条件的结果集。
2.安全,使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个行某个列,但是通过视图就可以简单的实现
3.数据独立,一旦视图的结果确定了,可以屏蔽表单的结构变化对用户的影响,原表增加列对视图没有影响,原表修改列名则可以通过修改视图来解决,不会造成对访问者的影响。
创建或者修改视图:
限制:
1.from关键字后面不可以包含子查询,这和其他数据库是不同的,如果视图是从其他数据库迁移过来的,可以将子查询的内容先定义成一个视图,然后对视图再创建视图就可以实现类似的功能了。
2.以下类型的视图不能更新:
1.包含以下关键字的SQL语句:聚合函数(sum、avg、min、max)、distinct、group by、having、union或者union all 2.常量视图 3.select中包含子查询 4.join 5.from 6.where子句的子查询引用了from中的表
创建视图: CREATE [OR REPLACE] [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION] 修改视图: ALTER [ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}] [DEFINER = { user | CURRENT_USER }] [SQL SECURITY { DEFINER | INVOKER }] VIEW view_name [(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK OPTION] OR REPLACE:表示替换已有视图 ALGORITHM:表示视图选择算法,默认算法是UNDEFINED(未定义的):MySQL自动选择要使用的算法 ;merge合并;temptable临时表 select_statement:表示select语句 [WITH [CASCADED | LOCAL] CHECK OPTION]:决定了是否允许更新数据使记录不再满足视图的条件。 local:只要满足本视图的条件就可以更新 cascade:是默认值,必须满足所有针对该视图的所有视图的条件才可以更新 create view v_F_players(编号,名字,性别,电话) as select PLAYERNO,NAME,SEX,PHONENO from PLAYERS where SEX='F' with check option;
删除视图:
DROP VIEW [IF EXISTS] view_name [, view_name] ...
存储过程:存储过程和函数是事先经过编译并存储在数据库中的一段SQL语句集合。区别在于函数必须有返回值,参数只有in,而存储过程没有,存储过程的参数可以使用in、out、inout类型。
创建存储过程和函数:
LANGUAGE SQL:说明下面过程的body是使用SQL语言编写的,这条是系统默认的,为今后mysql会支持的除SQL外的其他语言支持的存储过程准备
[NOT] DETERMINISTIC:DETERMINISTIC确定的,即每次输入一样输出一样的程序。NOT DETERMINISTIC非确定的,默认是非确定的。当前这个特征值还没有被优化
{ CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }:
CONTAINS SQL:子程序不包含读或者写数据的语句(默认值)
NO SQL:子程序不包含SQL语句
READS SQL DATA:子程序包含读数据语句但不包含写数据语句
MODIFIES SQL DATA:表示子程序包含写数据的语句。
SQL SECURITY { DEFINER | INVOKER }:可以用来指定子程序该用创建子程序者的许可来执行,还是使用调用者的许可来执行,默认DEFINER
COMMENT 'string':注释
CREATE PROCEDURE sp_name ([proc_parameter[,...]]) [characteristic ...] routine_body CREATE FUNCTION sp_name ([func_parameter[,...]]) RETURNS type [characteristic ...] routine_body proc_parameter: [ IN | OUT | INOUT ] param_name type func_parameter: param_name type type: Any valid MySQL data type characteristic: LANGUAGE SQL | [NOT] DETERMINISTIC | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string' routine_body: Valid SQL procedure statement or statements ALTER {PROCEDURE | FUNCTION} sp_name [characteristic ...] characteristic: { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA } | SQL SECURITY { DEFINER | INVOKER } | COMMENT 'string'
调用过程的语法:
call sp_name([parameter[,...]])
删除:
DROP {PROCEDURE | FUNCTION} [IF EXISTS] sp_name
例子
DROP PROCEDURE IF EXISTS Pro_Employee; DELIMITER $$ CREATE PROCEDURE Pro_Employee(IN pdepid VARCHAR(20),OUT pcount INT ) READS SQL DATA SQL SECURITY INVOKER BEGIN SELECT COUNT(id) INTO pcount FROM Employee WHERE depid=pdepid; END$$ DELIMITER ;
变量的定义:declare可以定义一个局部变量,该变量的左右范围只能在begin end块中,可以用在嵌套的块中,变量的定义必须写在复合语句的开头,并且在任何其他语句的前面。可以一次声明多个相同的类型的变量,default可以设置默认值。
declare var_name[,...] type [default value] set var_name = expr[,var_name = expr]...
事务控制:
chain和release:分别用来定义在事务提交或者回滚之后的操作,chain会立即启动一个新事务,并且和刚才的事务具有相同的隔离级别,release则会断开和客户端的连接。
set autocommit可以修改当前连接的提交方式,如果设置为0则之后的事务都需要显式的提交事务。
start transaction | begin commit [work] [and [no] chain] [[no] release] rollback [work] [and [no] chain] [[no] release] set autocommit = {0 | 1}
SQL优化:
索引问题:
1.对于多列索引,只要查询的条件中用到了最左边的列,索引一般就会被用到,如果不是第一列则不会用到索引。
2.对于使用like的查询,后面如果是常量并且只有%号不在第一个字符,索引才可能会被使用。
3.如果列名是索引,使用columnname is null将使用索引。
4.用or分隔开的条件,如果or前的条件中的列是索引但是后面的列没有索引则都不会用到索引。
select语句执行顺序:执行过程中也会相应的产生多个虚拟表,以配合最终的正确查询。
1.from:多表查询效率慢,不要join超过三张表。
2.on:
3.join:
4.where:
5.group by:实质是先排序后分组,默认对指定字段去重
6.having:
7.select:
8.distinct:不管是加不加索引 group by 都比 distinct 快。因此使用的时候建议选 group by
9.order by:
10.limit:全表扫描,速度会很慢且有的数据库结果集返回不稳定。建立主键或唯一索引, 利用索引。
explain select语句:分析SQL效率
select_type:表示select的类型,常见的取值有simple(简单表,即不使用表连接或子查询)、primary(主查询即外层的查询)、union(union中的第二个或者后面的查询语句)、subquery(子查询中第一个select)
table:输出结果的表
type:表示表的连接类型,性能由好到差system(常量表)、const(单表中最多有一个匹配行,例如primary key或者unique key)、eq_ref(对于前面的每一行,在此表中只查询一条记录,就是多表查询中只使用primary key或者unique key)、ref(与eq_ref类似,但是使用普通索引)、ref_or_null(与ref类似,区别在于对于null的查询)、index_merge(索引合并优化)、unique_subquery(in的后面是一个查询主键字段的子查询)、index_subquery(与unique_subquery类似,区别在于in的后面是查询非唯一索引字段的子查询)、range(单表中的范围查询)、index(对于前面的每一行,都通过查询索引来得到数据)、all(全表查询)
possible_keys:表示查询时,可能使用的索引
key:表示实际用到的索引
key_len:索引字段的长度
row:扫描行的数量
extra:执行情况的说明和描述