数据库:存储数据管理数据的仓库
类型:
1.关系型(有特定的组织方式,以行和列的形式存储数据):Mysql,SQLServer,Access,Oracle
2.非关系型:MongoDB ,Redis,Solr、ElasticSearch、Hive、HBase
数据库三范式:
1)原子性:列或字段不能再分,要求属性具有原子性,不可再分离
2)唯一性:一张表只说一件事是对记录的唯一性约束,要求记录有唯一标识
3)直接性:数据不能存在传递关系,即每个属性都和主键有直接关系
数据库储存引擎:
两个储存引擎
1.MyISMA储存引擎:
MySQL5.5版本之前的默认存储引擎,支持表级锁(表级锁是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁);不支持事务,外键。
使用场景:对事务的完整性没有要求,或以select、insert为主的应用基本都可以选用MYISAM。在Web、数据仓库中应用广泛。
特点:1,不支持事务外键;
2,2、每个myisam在磁盘上存储为3个文件,文件名和表名相同,扩展名分别是
.frm -------存储表定义 .MYD --------MYData,存储数据 .MYI --------MYIndex,存储索引
2.InnoDB储存引擎
主要特点:MySQL5.5版本之后的默认存储引擎;支持事务;
支持行级锁(行级锁是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁);
支持聚集索引方式存储数据。
MySQL的端口号是3306,SQLServer的端口号是1433,查了一下Oracle的端口号是1521
数据库主要特点:
(1)实现数据共享。
数据共享包含所有用户可同时存取数据库中的数据,也包括用户可以用各种方式通过接口使用数据库,并提供数据共享。
(2)减少数据的冗余度。
同文件系统相比,由于数据库实现了数据共享,从而避免了用户各自建立应用文件。减少了大量重复数据,减少了数据冗余,维护了数据的一致性。
(3)数据的独立性。
数据的独立性包括数据库中数据库的逻辑结构和应用程序相互独立,也包括数据物理结构的变化不影响数据的逻辑结构。
(4)数据实现集中控制。
文件管理方式中,数据处于一种分散的状态,不同的用户或同一用户在不同处理中其文件之间毫无关系。利用数据库可对数据进行集中控制和管理,并通过数据模型表示各种数据的组织以及数据间的联系。
(5)数据一致性和可维护性,以确保数据的安全性和可靠性。
主要包括:①安全性控制:以防止数据丢失、错误更新和越权使用;
②完整性控制:保证数据的正确性、有效性和相容性;
③并发控制:使在同一时间周期内,允许对数据实现多路存取,
又能防止用户之间的不正常交互作用;
④故障的发现和恢复:由数据库管理系统提供一套方法,
可及时发现故障和修复故障,从而防止数据被破坏
(6)故障恢复。
由数据库管理系统提供一套方法,可及时发现故障和修复故障,从而防止数据被破坏。数据库系统能尽快恢复数据库系统运行时出现的故障,可能是物理上或是逻辑上的错误。比如对系统的误操作造成的数据错误等。
SQL语句:结构化查询语言
DML:数据库操作语言 :insert(插入),delete(删除), update(修改), select(检索)
DQL:数据库查询语言 :select 语言
DDL:数据库定义语言:create table
DCL :数据库控制语言:grant/deny/revoke-----只有管理员才有相应权限
SQL不区分大小写,Orcal全大写
数据库操作:
新增: create database 数据库名字 default character set utf8;
查询:show datdbases;
删除:drop databases;
表的常见操作:
使用数据库:use 数据库名
新建一个数据库:
create table 表名(字段名 字段类型(字段长度),字段名2 字段类型(字段长度))default character set utf8;
主键自增:主键名 int primary key auto_increment
查询:show tabales;
修改指定表::修改 表 表名 添加 列/字段 列名 类型 长度
alter table a add column age int (5);
删除指定表:删除 表 表名
drop table 表名;
描述表: 描述 表名;
desc user;
关于数据的常见操作:
查询:查询 所有 来自 表名;
select * from user; * 可以替换具体的字段名,
插入:insert into 表名 values (1,2,3,4);post
修改:修改 表名 设置 字段名=新值; put
update User set name = "詹三";
update User set age =5820;
修改多个字段 update User set name=“实施计划书”, age = 42;
删除数据:delete from User;
字段约束:用来约束字段的值,通常是在创建表的时候就已经确定什么字段该用什么约束
唯一约束:unique 字段值唯一不能重复,
e.g. create table b(idcard varchar(7527) unique);
非空约束:约束的字段值不能为空 not null
e.g. create table n(name varchar(10 )unique, pwd varchar(40)not null)
主键约束:每个表都设计一个字段是主键,然后这个字段的值必须唯一并非空
----主键自增策略:直接交给数据库 主键约束primary 自增auto_increment
create table v (id int primary key auto_increment);
数据库约束constraints:主键primary key 非空not null 默认default 唯一unique 检查check
外键foreign key
数据库中基础类型的限制
int后面可以不设置长度,因为数据库在数据类型范围内不会限制长度
但是字符型的必须要用双引号或者单引号,否则报错
mysql中添加double字段的语句 double(4,3) 表示总位数为4,小数点后面三位数
Mysql基础函数
lower:数据转小写:select ‘ABC‘ ,lower(’ABC‘)from dept;
upper:数据转大写:select upper (dname) from dept ;
length: 数据长度:select length (dname)from dept;
substr:截取一定长度:select dname ,substr(dname,1,3) from dept; 取[ 1, 3 ]
concat :拼接数据:select dname ,concat (dname,'123') X from dept ;
replace : 把a替换成666:select dname,replace(dname,'a','666') X from dept;
ifnull:判断,如果commer 为null,用1000代替 select ifnull (commer,1000) commer from dept;
round四舍五入(取整) select commer ,round(commer) from emp;
round四舍五入(保留一位小数) select commer ,ceil(commer,1) from emp;
ceil向上取整 select commer,ceil(commer) from emp;
ceil向上保留一位小数 select commer ,ceil (commer,1) from emp;
floor向下取整 select commer ,floor(commer) from emp;
floor向下保留一位小数:select commer,floor(commer,1) from emp;
now 年与日,时分秒 curdate 年与日 curtime 时分秒
select now();
select curdate();
select curtime();
hour()时--minute()分--second()秒
select now(),hour(now( )),minute(now( )),second(now()) from emp;
year()年 --mother()月--day ()日
select now(),year(now()),mother(now()),day(now()) from emp;
转义字符:作为sql语句符号,内容中出现单撇就会乱套,进行转义即可。
select ‘ab'cd'--单引号是一个特殊字符
select 'ab\'cd'--数据中有单引号,用一个\转义成普通字符
条件查询:
distinct :去除重复字段
select loc from dept ;----->select distinct loc from dept;
where:不能使用列别名
select * from emp;
select * from emp where 1=1; 类似条件没有
select * from emp where 1=0; 条件不成立
select * from emp where empno=100;唯一条件
select * from emp where ename="Tom" and deptno=2; 相当于两个条件的&关系
select * from emp where ename="Tom" or deptno=2; 相当于俩个条件并列的关系
select name ,sal from emp where sal =1400 or sal= 1600 or sal =1800;
select name ,sal from emp where sal in(1400,1600,1800);
select name,sal from emp where not in (1400,1600,1800);
like: 模糊查询
select * from emp where ename like ''1%"; 表示以1开头
like后面的“%1”表示以1结尾; “%1%”包含1
like后面“1_ _ ” 表示后面有两个字符,其中 _ 代表一个字符位置
null
select * from emp where mar is null;过滤字段为空
select * from emp where mar is not null;过滤字段不为空
between and 区间范围,两边都包含
select * from emp;
select * from emp where sal<300 and sal>1000;
select * from emp where sal<=300 and sal>=1000;等效
select * from emp where sal between 300 and 1000;等效
limit :分数最高的记录:按照分数排序后,limit n 返回前n条
mysql中用limit 分页查询
SELECT * FROM emp LIMIT 2 #取前两条
select * from emp where limit 0,2;从第一条开始,展示前两条
select * from emp where limit 1,2;第二条开始,展示两条记录
order by
select * from emp order by sal 默认升序 asc
select * from emp order by sal desc ;降序
SELECT * FROM emp ORDER BY sal DESC LIMIT 1;查询最高薪的员工的名字和岗位
统计案例
#2.聚合函数: max min sum avg count,重点!!
#练习3:获取最大值
SELECT sal FROM emp
SELECT MAX(sal) FROM emp
#练习4:获取最小值
SELECT MIN(sal) FROM emp
#练习5:求工资的总和
SELECT SUM(sal) FROM emp
#练习6:求平均工资
SELECT AVG(sal) FROM emp
#练习7:求个数
SELECT COUNT(comm) FROM emp#不推荐!!不统计null的,低效
SELECT COUNT(sal) FROM emp#不推荐!!
SELECT COUNT(*) FROM emp#高效
SELECT COUNT(1) FROM emp#高效
#练习8:统计2019年以前入职的员工人数
SELECT COUNT(1) FROM emp WHERE YEAR(hiredate)<2019
#练习9:统计2019年以前入职的员工的平均工资
SELECT AVG(sal) FROM emp WHERE YEAR(hiredate)<2019
#练习10:统计2号部门的最高薪
SELECT MAX(sal) FROM emp WHERE deptno=2
#练习11:统计岗位是员工的平均工资
SELECT AVG(sal) FROM emp WHERE job='员工'
分组 group 用于对查询结果进行分组统计
#1.分组:使用group by
#问题1:什么时候必须要分组???查询结果中出现了混合列
#问题2:按啥分组???按照非聚合列分组
#当查询结果中,出现了混合列的时候,必须分组!!!
#聚合列,使用了聚合函数.非聚合列,没有使用聚合函数
SELECT job,AVG(sal) FROM emp #不对
#按照合理的需求分组:job deptno hiredate
#练习1:统计每个岗位的平均薪资
SELECT job,AVG(sal) FROM emp
GROUP BY job #按照岗位分组
#练习2:统计每个岗位的员工人数并排序
SELECT job,COUNT(1) a FROM emp
GROUP BY job#分组
ORDER BY a DESC#降序,默认是升序
#练习3:统计每个部门的最高薪
SELECT deptno,MAX(sal) FROM emp
GROUP BY deptno
#练习4:统计每个部门的总人数
SELECT deptno,COUNT(*) FROM emp
GROUP BY deptno
#练习5:统计每年入职的总人数
SELECT YEAR(hiredate),COUNT(1) FROM emp
GROUP BY YEAR(hiredate)
#练习6:统计每年入职的工资总支出
SELECT YEAR(hiredate),SUM(sal)*12 FROM emp
GROUP BY YEAR(hiredate)
分组后过滤 having
#2.分组后的过滤having
#练习7:统计每年入职的工资总支出,只要15年以后的数据
SELECT YEAR(hiredate) a,SUM(sal) FROM emp
GROUP BY a #按照非聚合列分组
HAVING a>2015 #分组后的条件
#练习8:统计每个部门的总人数,只要人数>2的数据
SELECT deptno,COUNT(1) a FROM emp
GROUP BY deptno
HAVING a>2
Spring boot 一次查询两个数据库:多线程开启两次连接,配置两个数据源;
也可以直接使用JDBC连接的方式直接连接数据库
truncate和delete区别:
truncate | delete | |
---|---|---|
主要区别 | 删除表中数据,不删除表结构,释放空间 | 删除内容,不删除表结构,不释放空间
|
内存空间 | 删除数据后重新写入数据会从1开始 | 从删除前的最后一行续写 |
处理速度 | 从1开始,即全部清空开始,速度快 | 从当前行数开始读写,速度慢 |
语句类型 | truncate 和 drop属于DDL(数据库定义语言),执行后自动commit,对于事务不可以回滚 | 属于DML(数据库操作语言)可以由操作者提交和回滚事务 |
语法结构 | truncate 表名(删除表中数据,无法回滚) | delete from 表名(where ..可写可不写,写的话选择性删除,不选的话清空表数据) |
保证多条SQL要么全成功,否则全失败
四个特性:
原子性:多条SQL是一个密不可分的整体
一致性:分布式系统里,数据的一致性
隔离性:数据库支持高并发,使用了锁的机制保证了数据的安全
持久性:是指对数据的增删改是持久生效的
隔离级别
读未提交:read uncommitted:读未提交, 安全性最差,但是效率高 (会产生脏读问题,在项目中基本不怎么用)
读已提交:read committed:读已提交, 安全性较好,但是效率较差,也是Oracle的默认级别(
会避免脏读问题;
由于一个事务可以看到别的事务已经提交的数据,于是随之而来产生了不可重复读和虚读等问题
)
可重复读:repeatable read:可重复读,安全性适中,但是效率一般,也是MySQL的默认级别(它确保了一个事务中多个实例在并发读取数据的时候会读取到一样的数据;不过理论上,这会导致另一个棘手的问题:幻读 (Phantom Read)。简单的说,幻读指当用户读取某一范围的数据行时,另一个事务又在该范围内插入了新行,当用户再读取该范围的数据行时,会发现有新的“幻影” 行。InnoDB和Falcon存储引擎通过多版本并发控制(MVCC,Multiversion Concurrency Control)机制解决了该问题。)
串行化:serializable:串行化,安全性最高,但是效率太差(通过强制事务排序,使之不可能相互冲突,从而解决幻读问题。简言之,它是在每个读的数据行上加上共享锁。在这个级别,可能导致大量的超时现象和锁竞争,一般为了提升程序的吞吐量不会采用这个;)
四种表的关系:
1--1 1--n n--1 n--n
多表联查:三种方式:迪卡尔积/连接查询/子查询
笛卡尔积:(交叉连接)多表之间用 逗号 ‘’,''连接,用where 表示两张表的关系(两张表的相同字段)
#多表联查方式1:笛卡尔积
#练习1:查询部门表和员工表的所有数据
SELECT * FROM dept,emp
#添加查询条件,表明两张表的关系
SELECT * FROM dept,emp #逗号隔开表名
#表名.字段名 表名.字段名
WHERE dept.deptno = emp.deptno
#练习2:查询课程表和老师表的所有数据
#select * from courses,teachers
SELECT courses.*,teachers.* FROM courses,teachers
WHERE courses.tno=teachers.tno
#练习3:查询在一区办公的员工名字
SELECT emp.ename FROM emp,dept
WHERE emp.deptno=dept.deptno #描述两个表的关系
AND dept.loc='一区' #在一区办公
#练习4:查询在research部门工作的员工的信息
SELECT emp.*,COUNT(1) FROM emp,dept
WHERE emp.deptno=dept.deptno #描述两个表的关系--写的是两张表的关联字段
AND dept.dname='research' #在research部门的
GROUP BY emp.deptno#按照非聚合列分组,必须是合理的分组需求
2.连接查询(多表之间用join 连,用 on 描述两表关系,用where表示更多条件)
e.g. 查学院李俊总得分
select sum (scores,degree) from students
join scores on students.son=sccres.son
where students.sname="李俊";
#多表联查方式2:连接查询
#语法:多表之间用join连接,用on来描述两张表的关系,用where表示更多的条件
#练习1:查询在一区办公的员工名字
SELECT emp.ename FROM emp JOIN dept
ON emp.deptno=dept.deptno #描述两表的关系
WHERE dept.loc='一区' #在一区办公的
#练习2:查询员工表和部门表的所有数据
SELECT * FROM emp JOIN dept
ON emp.deptno=dept.deptno
#练习3:查询在research部门工作的员工的信息
SELECT emp.* FROM dept JOIN emp
ON dept.deptno=emp.deptno
WHERE dept.dname='research'#在research部门
#练习4:查询易天老师能讲的课程名称
SELECT courses.cname FROM teachers JOIN courses
ON teachers.tno=courses.tno #表关系
WHERE teachers.tname='易天' #易天老师
#练习5:查询学员李军的总得分
SELECT SUM(scores.degree) FROM students JOIN scores
ON students.sno = scores.sno
WHERE students.sname='李军'#学员李军
#连接查询:内连接,外连接
#内连接:inner join取交集,可以简写成join
#左外 连接:left join取左表的所有和右表满足的
#右外 连接:right join取右表的所有和左表满足的
#练习:查询部门表和员工表的所有数据
SELECT * FROM emp INNER JOIN dept
#内连接,取交集
ON dept.deptno=emp.deptno
#连接查询优化方案:小表驱动大表
SELECT * FROM dept LEFT JOIN emp
#左连接,取到左表的所有和右表满足条件的不满足用null填充
ON dept.deptno=emp.deptno
SELECT * FROM emp RIGHT JOIN dept
#右连接,取到右表的所有和左表满足条件的不满足用null填充
ON dept.deptno=emp.deptno
3子查询(也称为嵌套查询,把上次的查询结果当作这次查询的条件使用)
单行子查询=
多行子查询 in
#多表联查方式3:子查询
#练习1:查询accounting部门的员工信息
#第一次查:根据部门名称查部门编号--查dept
SELECT deptno FROM dept WHERE dname='accounting'
#第二次查:根据部门编号查员工信息--查emp
SELECT * FROM emp WHERE deptno=1
#嵌套查询:
SELECT * FROM emp WHERE deptno=(
SELECT deptno FROM dept WHERE dname='accounting'
)
#练习2:查询tony所在的部门名称
#2.2.拿着部门编号查部门名称
SELECT dname FROM dept WHERE deptno =(
#2.1.拿着员工的名字查部门编号
SELECT deptno FROM emp WHERE ename='tony'
)
#练习3:查询在二区办公的员工姓名
#第一次查:根据部门地址查部门编号
SELECT deptno FROM dept WHERE loc='二区'
#第二次查:根据部门编号查员工名字
#select ename from emp where deptno = 2,3 #语法不对
#SELECT ename FROM emp WHERE deptno in (2,3)#对,用in表示多个值
#嵌套查询:
SELECT ename FROM emp WHERE deptno IN(
SELECT deptno FROM dept WHERE loc='二区'
)
#练习4:查询高于平均薪资的员工信息
SELECT * FROM emp WHERE sal>(
SELECT AVG(sal) FROM emp
)
SQL面试题
查询所有记录
select * from emp
只查询指定列
SELECT id,ename,sal from emp
查询id为100的记录
select * from emp where id=100
模糊查询记录
select * from emp where ename like 'j%' #以j开头的记录
select * from emp where ename like '%k' #以k结束的记录
select * from emp where ename like '%a%' #包含a的记录
select * from emp where ename not like 'j%' #不 以j开头的记录
查询之间范围之间的所有记录
select * from emp where sal between 8000 and 20000 #[8000,20000]
select * from emp where sal>8000 and sal<20000 #(8000,20000)
查询满足两个条件的记录
SELECT * from user where age=19 or age=20 #或者关系
SELECT * from user where age in (19,20)
SELECT * from user where age=20 and name='xiongda' #并且关系
查询用户住址
SELECT distinct addr from user
查询19岁人的名字
SELECT distinct name from user where age=19
按age升序查询记录
SELECT * from user order by age asc #升序,默认
SELECT * from user order by age desc #降序
以name升序、age降序查询记录
SELECT * from user order by name asc,age desc #name升序,age降序
查询总人数
SELECT count(*) from user
SELECT count(1) from user
SELECT count(id) from user
查询各个城市的人数
select addr,count(addr) from user group by addr #聚合函数以外的列要分组
查询至少有2人的地址
SELECT addr,count(name) from user GROUP BY addr
SELECT addr,count(name) X from user GROUP BY addr having X>2 #条件过滤
查询记录中最年长和最年轻
select max(age),min(age) from user
查询大于平均年龄的记录
select * from user where age > (select avg(age) from user)
查询年龄最大的用户信息
select * from user where age = (select max(age) from user)
查询各部门的最高薪
select id,name,sal,max(sal) from emp GROUP BY deptno
查询各科的平均工资
select avg(comm) from emp
select ROUND(avg(comm),1) from emp #保留一位小数
SELECT * from emp where comm > (select avg(comm) from emp)
查询id是100或200的记录
select * from emp where id=100
select * from emp where id=200
select * from emp where id=100 or id=200
select * from emp where id in(100,200)
select * from emp where id=200
#UNION #合并重复内容
union all #不合并重复内容
select * from emp where id=200
查询存在部门的员工信息
select * from emp where deptno in (select id from dept)
查询没划分部门的员工信息
select * from emp where deptno not in(select id from dept)
查询同名的员工记录
select * from emp WHERE ename in (
select ename from emp GROUP BY ename HAVING count(ename)>1
)
全部学生按出生年月排行
select * from students order by sbirthday #数值从小到大,年龄就是大到小了
每个班上最小年龄的学员
select sname,class,max(sbirthday) from students group by class #数字最大,年龄是最小的
查询学生的姓名和年龄
select sname,year(now())-year(sbirthday) age from students
查询男教师及其所上的课程
SELECT * from teachers a inner JOIN courses b on a.tno=b.tno AND a.tsex='男'
SELECT * from teachers a,courses b where a.tno=b.tno AND a.tsex='男'
查询每个老师教的课程
SELECT c.cname,t.tname,t.prof,t.depart
FROM teachers t
LEFT JOIN courses c ON t.tno = c.tno
查询女老师的信息
SELECT *
FROM teachers t
LEFT JOIN courses c ON t.tno = c.tno
where t.tsex='女'
第一种先连接数据后过滤数据,假如数据量很大,第一种中间过程要构建巨大的临时表。而第二种方式先过滤数据,构建的中间结果集自然就变的很小。所占内存,所加工的时间所网络传输的时间都变少了,所以效率高。
查询得分前3名的学员信息
select * from scores order by degree desc limit 3 #前三条
select * from scores order by degree desc limit 1,3
#从1位置(第二条)开始,总共取3条
查询课程是“计算机导论”的,得分前3名的学员信息
select * from scores where cno = (select cno from courses where cname='计算机导论')
order by degree desc limit 3
课程号“3-105”的倒数最后3名学员排行
select * from scores where cno='3-105' order by degree limit 3
SQL执行顺序?
(1) FROM [left_table] 选择表
(2) ON
(3)
(4) WHERE
(5) GROUP BY
(6) AGG_FUNC(column or expression),... 聚合
(7) HAVING
(8) SELECT (9) DISTINCT column,... 选择字段、去重
(9) ORDER BY
(10) LIMIT count OFFSET count; 分页
概念:索引存储在内存中,为服务器存储引擎为了快速找到记录的一种数据结构。索引的主要作用是加快数据查找速度,提高数据库的性能。
索引本身很大,往往以索引文件的形式存放在磁盘中。
优点 | 缺点 |
索引是数据库优化 | 本身就是一张虚表,保存了主键与索引字段,并指向实体表记录,占空间 |
表的主键会默认自动创建索引 | 表中内容在业务表中都有,数据重复,空间造成浪费 |
每个字段都可以被索引 | 对数据库的增删改操作需要更新索引信息,如数据量大,更新变慢 |
大量降低数据库的IO磁盘读写成本,提高了检索速度 | 在业务增加的同时不断更新索引 |
事先对数据进行排序,提高查询效率 |
优点:
1)创建唯一索引,确定数据库每一行数据的唯一性
2)加快数据的检索速度
3)加快表和表的连接,实现数据的参考完整性
4)在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
索引分类
普通 :最基本的索引,它没有任何限制。
唯一 :和普通索引类似,不同的是索引列的值必须唯一,但允许有空值。如果是组合索引,则列值的组合必须唯一。
主键:它是一种特殊的唯一索引,用于唯一标识数据表中的某一条记录,不允许有空值,一般用 primary key 来约束
联合(又叫复合索引):多个字段上建立的索引,能够加速复合查询条件的检索。
全文 :老版本 MySQL 自带的全文索引只能用于数据库引擎为 MyISAM 的数据表,新版本 MySQL 5.6 的 InnoDB 支持全文索引。默认 MySQL 不支持中文全文检索,可以通过扩展 MySQL,添加中文全文检索或为中文内容表提供一个对应的英文索引表的方式来支持中文。
索引底层实现原理:
创建索引:
查看索引:show index from dept;
创建普通索引:cerate index 索引名字 on 表名(字段名);
create index loc_dept on dept(loc);
创建唯一索引:cerate unique index 索引名 on 表名(字段名);
创建复合索引:希望索引不止一个列,可以在括号中列出这些表的名称,用逗号隔开;
create index 索引名 on 表名 (字段1,字段二);
删除索引:alter table 表名 drop index 索引名;
alter table dept drop index deu_dedlk;
索引扫描类型:
type:
ALL全表扫描,没有优化,最慢的方式
index 索引全扫描,常用语 <, <=, >=, between等操作;
ref 使用非唯一索引扫描或者唯一索引前缀扫描,返回单条记录,常出现在关联查询中
re_ref类似ref,区别在于使用的是唯一索引,使用主键的关联查询。
const/system 单条记录,系统会把匹配行中的其他列作为常数处理,如主键或者唯一主键查询,system是const的特殊情况
null MySQL不访问任何表或者索引,直接返回结果。
最左特性:
explain #解释 可以分析SQL执行计划,看是否最佳主要是看SQL是否使用了索引
select * from dept where loc='二区'#使用了loc索引
explain
select * from dept where dname='研发部'# 使用dname索引
explain
select * from dept where dname='二区'and dname='研发部';
1.用字段名代替 *
2.where 后面,用 = ,and (过滤条件精细) ,尽量不要用!=,or,in
3.字段类型,尽量用varchar ,字段值尽量用数字,不要用字符串
4.索引,单表索引最多5个
5.模糊查询最好确定以什么开头,高效而且索引会生效
6.字符串,SQL对于数字不严格,where name=123,索引会失效;
数字加引号,‘123’就变成一个字符串,索引就会生效
1.对查询频次较高, 且数据量比较大的表, 建立索引
2.索引字段的选择, 最佳候选列应当从where子句的条件中提取, 如果where子句中的组合比较多, 那么应当挑选最常用, 过滤效果最好的列的组合.
3.使用唯一索引, 区分度越高, 使用索引的效率越高.
4.索引并非越多越好, 如果该表赠,删,改操作较多, 慎重选择建立索引, 过多索引会降低表维护效率
5.使用短索引, 提高索引访问时的I/O效率, 因此也相应提升了Mysql查询效率
6.如果where后有多个条件经常被用到, 建议建立符合 索引, 复合索引需要遵循最左前缀法则, N个列组合而成的复合索引, 相当于创建了N个索引.
复合索引命名规则 index_表名_列名1_列名2_列明3
比如:create index idx_seller_name_sta_addr on tb_seller(name, status, address)
避免索引失效?六条
1,如果在查询的时候, 使用了复合索引, 要遵循最左前缀法则, 也就是查询从索引的最左列开始, 并且不能跳过索引中的列.
2,尽量不要在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描
3,应尽量避免在 where 子句中使用 != 或 <> 操作符,否则将引擎放弃使用索引而进行全表扫描
4,不做列运算where age + 1 = 10,任何对列的操作都将导致表扫描,它包括数据库教程函数.计算表达式等, 都会是索引失效
5,查询 like,如果是 ‘%aaa’ 也会造成索引失效
6,应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引,将导致引擎放弃使用索引而进行全表扫描