当前数据库分为关系型数据库和非关系型数据库
关系型数据库
关系型数据库:指采用了关系模型来组织数据的数据库。
关系模型指的就是二维表格模型,而一个关系型数据库就是由二维表及其之间的联系所组成的一个数据组织。
关系模型中常用的概念:
关系:一张二维表,每个关系都具有一个关系名,也就是表名
元组:二维表中的一行,在数据库中被称为记录
属性:二维表中的一列,在数据库中被称为字段
域:属性的取值范围,也就是数据库中某一列的取值限制
关键字:一组可以唯一标识元组的属性,数据库中常称为主键,由一个或多个列组成
关系模式:指对关系的描述。其格式为:关系名(属性1,属性2, ... ... ,属性N),在数据库中成为表结构
关系型数据库的优点:
1.容易理解:二维表结构是非常贴近逻辑世界的一个概念,关系模型相对网状、层次等其他模型来说更容易理解
2.使用方便:通用的SQL语言使得操作关系型数据库非常方便
3.易于维护:丰富的完整性(实体完整性、参照完整性和用户定义的完整性)大大减低了数据冗余和数据不一致的概率
关系型数据库存在的问题
1.网站的用户并发性非常高,往往达到每秒上万次读写请求,对于传统关系型数据库来说,硬盘I/O
是一个很大的瓶颈
2.网站每天产生的数据量是巨大的,对于关系型数据库来说,在一张包含海量数据的表中查询,效率是非常低的
3.在基于web的结构当中,数据库是最难进行横向扩展的,当一个应用系统的用户量和访问量与日俱增的时候,数据库却没有办法像web server
和app server
那样简单的通过添加更多的硬件和服务节点来扩展性能和负载能力。当需要对数据库系统进行升级和扩展时,往往需要停机维护和数据迁移。
4.性能欠佳:在关系型数据库中,导致性能欠佳的最主要原因是多表的关联查询,以及复杂的数据分析类型的复杂SQL报表查询。为了保证数据库的ACID特性,必须尽量按照其要求的范式进行设计,关系型数据库中的表都是存储一个格式化的数据结构。
数据库事务必须具备ACID
特性,ACID
分别是Atomic
原子性,Consistency
一致性,Isolation
隔离性,Durability
持久性。
当今十大主流的关系型数据库
Oracle,Microsoft SQL Server,MySQL,PostgreSQL,DB2,
Microsoft Access, SQLite,Teradata,MariaDB(MySQL的一个分支),SAP
非关系型数据库
非关系型数据库:指非关系型的,分布式的,且一般不保证遵循ACID
原则的数据存储系统。
非关系型数据库结构
非关系型数据库以键值对存储,且结构不固定,每一个元组可以有不一样的字段,每个元组可以根据需要增加一些自己的键值对,不局限于固定的结构,可以减少一些时间和空间的开销。
优点
1.用户可以根据需要去添加自己需要的字段,为了获取用户的不同信息,不像关系型数据库中,要对多表进行关联查询。仅需要根据id
取出相应的value
就可以完成查询。
2.适用于SNS(Social Networking Services)
中,例如facebook,微博。系统的升级,功能的增加,往往意味着数据结构巨大变动,这一点关系型数据库难以应付,需要新的结构化数据存储。由于不可能用一种数据结构化存储应付所有的新的需求,因此,非关系型数据库严格上不是一种数据库,应该是一种数据结构化存储方法的集合。
不足:
只适合存储一些较为简单的数据,对于需要进行较复杂查询的数据,关系型数据库显的更为合适。不适合持久存储海量数据
非关系型数据库的分类
非关系型数据库都是针对某些特定的应用需求出现的,因此,对于该类应用,具有极高的性能。依据结构化方法以及应用场合的不同,主要分为以下几类:
面向高性能并发读写的key-value数据库:
key-value
数据库的主要特点是具有极高的并发读写性能Key-value
数据库是一种以键值对存储数据的一种数据库,类似Java
中的map
。可以将整个数据库理解为一个大的map
,每个键都会对应一个唯一的值。
主流代表为Redis, Amazon DynamoDB, Memcached,
Microsoft Azure Cosmos DB和Hazelcast
面向海量数据访问的面向文档数据库:
这类数据库的主要特点是在海量的数据中可以快速的查询数据
文档存储通常使用内部表示法,可以直接在应用程序中处理,主要是JSON
。JSON
文档也可以作为纯文本存储在键值存储或关系数据库系统中。
主流代表为MongoDB,Amazon DynamoDB,Couchbase,
Microsoft Azure Cosmos DB和CouchDB
面向搜索数据内容的搜索引擎:
搜索引擎是专门用于搜索数据内容的NoSQL数据库管理系统。
主要是用于对海量数据进行近实时的处理和分析处理,可用于机器学习和数据挖掘
主流代表为Elasticsearch,Splunk,Solr,MarkLogic和Sphinx
面向可扩展性的分布式数据库:
这类数据库的主要特点是具有很强的可拓展性
普通的关系型数据库都是以行为单位来存储数据的,擅长以行为单位的读入处理,比如特定条件数据的获取。因此,关系型数据库也被成为面向行的数据库。相反,面向列的数据库是以列为单位来存储数据的,擅长以列为单位读入数据。
这类数据库想解决的问题就是传统数据库存在可扩展性上的缺陷,这类数据库可以适应数据量的增加以及数据结构的变化,将数据存储在记录中,能够容纳大量动态列。由于列名和记录键不是固定的,并且由于记录可能有数十亿列,因此可扩展性存储可以看作是二维键值存储。
主流代表为Cassandra,HBase,Microsoft Azure Cosmos DB,
Datastax Enterprise和Accumulo
CAP理论
NoSQL的基本需求就是支持分布式存储,严格一致性与可用性需要互相取舍
CAP理论:一个分布式系统不可能同时满足C(一致性)、A(可用性)、P(分区容错性)三个基本需求,并且最多只能满足其中的两项。对于一个分布式系统来说,分区容错是基本需求,否则不能称之为分布式系统,因此需要在C和A之间寻求平衡C(Consistency)
一致性
一致性是指更新操作成功并返回客户端完成后,所有节点在同一时间的数据完全一致。与ACID的C完全不同A(Availability)
可用性
可用性是指服务一直可用,而且是正常响应时间。P(Partition tolerance)
分区容错性
分区容错性是指分布式系统在遇到某节点或网络分区故障的时候,仍然能够对外提供满足一致性和可用性的服务。
关系型与非关系型数据库的比较
1.成本:Nosql
数据库简单易部署,基本都是开源软件,不需要像使用Oracle
那样花费大量成本购买使用,相比关系型数据库价格便宜。
2.查询速度:Nosql
数据库将数据存储于缓存之中,而且不需要经过SQL
层的解析,关系型数据库将数据存储在硬盘中,自然查询速度远不及Nosql
数据库。
3.存储数据的格式:Nosql
的存储格式是key,value
形式、文档形式、图片形式等等,所以可以存储基础类型以及对象或者是集合等各种格式,而数据库则只支持基础类型。
4.扩展性:关系型数据库有类似join这样的多表查询机制的限制导致扩展很艰难。Nosql
基于键值对,数据之间没有耦合性,所以非常容易水平扩展。
5.持久存储:Nosql
不使用于持久存储,海量数据的持久存储,还是需要关系型数据库
6.数据一致性:非关系型数据库一般强调的是数据最终一致性,不像关系型数据库一样强调数据的强一致性,从非关系型数据库中读到的有可能还是处于一个中间态的数据,Nosql
不提供对事务的处理。
1.数据库启动
命令:mysql -uroot -proot
(注:-u后是你的数据库名-p后是你的数据库密码;具体内容以你的设置为本)
2.对数据库的操作(DOS窗口/可视化的工具)
(1)操作库的命令
查看所有的库: show databases ;
创建库: create database 库名;
删除库: drop database 库名;
(2)操作表的命令
使用库:use 库名;
查看表: show tables;
创建表: create table 表名(字段名 字段类型(长度) , 2 , 3 , 4 , 5…);
删除表: drop table 表名;
修改表: alter table 表名 add column 字段名 字段类型(长度)
描述表:desc 表名;
(3)对表中内容操作的命令
查询: select * from 表名 ;
创建: insert into 表名 values(字段1的值,字段2的值,字段3的值,字段4的值)
修改: update 表名 set 字段名=新值(where)
删除: delete from 表名(where)
一,字段约束
–1,概述
常见的约束: 主键约束 , 非空约束 , 唯一约束
–2,主键约束
表设计的原则是,表里必须有主键.作为每条记录的唯一标识.
当表里的字段加了主键约束时,效果是,字段的值必须唯一且不能为null
通常会使用自增策略,是指主键的值从此不必我们设计,交给了数据库来管理
#主键约束:给表里的某个字段设计约束,
#特点是字段值必须唯一且不能null
CREATE TABLE a(id INT PRIMARY KEY)
#主键自增策略:主键的值交给数据库维护管理(从1开始,++)
CREATE TABLE b(id INT PRIMARY KEY AUTO_INCREMENT)
–3,非空约束
#非空约束:字段的值不能是null
CREATE TABLE c(
id INT PRIMARY KEY AUTO_INCREMENT,#主键约束
PASSWORD VARCHAR(20) NOT NULL #非空约束,值不能是null
)
#c表里有两个字段,那就必须赋两个值,
#只是第一个是id的值不必维护
INSERT INTO c VALUES(NULL,'123456')
#INSERT INTO c VALUES(NULL,null),第二个必须不为null
–4,唯一约束
#唯一约束:值不能相同
CREATE TABLE e(
id INT PRIMARY KEY AUTO_INCREMENT,#主键约束
NAME VARCHAR(20) UNIQUE NOT NULL #唯一约束,值不能重复
)
二,基本函数
–1,概述
Mysql数据库提供了丰富的函数,
常见的: lower upper length concat substr replace ifnull round/ceil/floor
–2,测试
#只查指定列的值
#UPPER全转大写 LOWER全转小写
SELECT ename,UPPER(ename),LOWER(ename) FROM emp
`dept`#length求长度(一个字母算一个字符,一个汉字算三个字符)
SELECT LENGTH(ename),ename,LENGTH(job),job FROM emp
#concat(1,2,3)拼接字符串-1是字段名2和3都是要拼的内容
SELECT ename,CONCAT(ename,'hello',100) FROM emp
#查部门名称
#substr(1,2,3)截取字符串-1是字段名2是开始位置3是总长度
SELECT dname,SUBSTR(dname,2),SUBSTR(dname,2,3) FROM dept
#replace(1,2,3)替换-1是字段名2是要被替换的3是新的数据
SELECT dname,REPLACE(dname,'o','666') FROM dept
#ifnull(1,2)判断是否为null,如果是null就替换成0-1是字段名2是要替换的值
SELECT comm,IFNULL(comm,0) FROM emp
SELECT *,sal+IFNULL(comm,0) FROM emp
#round四舍五入/ceil向上取整/floor向下取整
SELECT comm,ROUND(comm),CEIL(comm),FLOOR(comm) FROM emp
#now/CURDATE/CURTIME
SELECT NOW() #年月日 时分秒
SELECT CURDATE()#年月日
SELECT CURTIME()#时分秒
#year/month/day/hour/minute/second
SELECT YEAR('2000-07-27')
SELECT YEAR(NOW()),MONTH(NOW()),DAY(NOW())
SELECT HOUR(NOW()),MINUTE(NOW()),SECOND(NOW())
三,条件查询
–1,where like
#查询部门地址
SELECT loc FROM dept
#DISTINCT用来给结果去重distinct
SELECT DISTINCT loc FROM dept
#where满足条件的才查出来
#查询deptno等于1的部门记录
SELECT * FROM dept WHERE deptno=1
#查询地址在一区的部门记录
SELECT * FROM dept WHERE loc='一区'
#查询地址在二区的部门名称
SELECT dname FROM dept WHERE loc='二区'
#根据名称查询部门记录
SELECT * FROM dept WHERE dname='research'
#根据名称和地址 查询部门记录
SELECT * FROM dept
#WHERE loc='二区' and dname='research2'#并且关系
WHERE loc='二区' OR dname='research2'#或者关系
SELECT * FROM dept
WHERE 1=1
#查询工资>8000的员工信息
SELECT * FROM emp WHERE sal>8000
#查询工资是8000的或者工资是3000的员工信息
SELECT * FROM emp WHERE
# sal=8000 or sal=3000
sal IN (3000,8000) #作用意义同上
SELECT * FROM emp WHERE
empno IN (100,300,500)
#like 像,模糊查询,通常配合%作为占位符
#查询名字里包含a的员工信息
SELECT * FROM emp WHERE
#ename like '%a%' #包含a,动态匹配0~n个字符
ename LIKE 'l%' #以l开头,动态匹配0~n个字符
–2,null limit order by等
#查询工资>8000的员工信息
SELECT * FROM emp WHERE sal>8000
#查询工资是8000的或者工资是3000的员工信息
SELECT * FROM emp WHERE
# sal=8000 or sal=3000
sal IN (3000,8000) #作用意义同上
SELECT * FROM emp WHERE
empno IN (100,300,500)
#like 像,模糊查询,通常配合%作为占位符
#查询名字里包含a的员工信息
SELECT * FROM emp WHERE
#ename like '%a%' #包含a,动态匹配0~n个字符
ename LIKE 'l%' #以l开头,动态匹配0~n个字符
#查询mgr是null的员工信息
SELECT * FROM emp
WHERE mgr IS NULL #是null
#WHERE mgr IS not NULL #不是null
#查询sal在3000到10000内的员工信息
SELECT * FROM emp WHERE
#sal > 3000 and sal< 10000
sal BETWEEN 3000 AND 10000 #包含[3000,10000]
#查询2017年到2019年入职的员工信息
SELECT * FROM emp WHERE
YEAR(hiredate) BETWEEN 2017 AND 2019 #包含
#limit分页
SELECT * FROM emp LIMIT 3 #只查前三条
#第1个数字是开始位置(从n+1条数据开始)第2个是总条数
SELECT * FROM emp LIMIT 0,3
SELECT * FROM emp LIMIT 2,2
#order by 排序
SELECT * FROM emp ORDER BY sal ASC #默认ASC,升序
SELECT * FROM emp ORDER BY sal DESC #倒序
SELECT * FROM emp ORDER BY hiredate #按照日期的数字升序
SELECT * FROM emp ORDER BY ename #a-z升序
SELECT * FROM emp ORDER BY job
#拿着每个汉字对应的数字(查u8) ,升序排序
四,统计案例
#统计2019年入职的员工
SELECT * FROM emp WHERE
#year(hiredate)=2019
hiredate>'2019-1-1' AND hiredate<'2019-12-12'
#统计2017年以前入职的员工
SELECT * FROM emp WHERE
YEAR(hiredate)<2017
#统计2015~2017年入职的员工
SELECT * FROM emp WHERE
YEAR(hiredate) BETWEEN 2015 AND 2017
#统计员工入职了几年
SELECT *,YEAR(NOW())-YEAR(hiredate) FROM emp
五,聚合函数
–1,概述
把一列的值全都取出来,聚合起来,分析最大值,最小值,平均值,求和,求个数 常见的聚合函数:
max min avg sum count
–2,测试
#聚合函数:把查出来的列聚合起来分析数据
#求最高薪max
SELECT sal FROM emp ORDER BY sal DESC LIMIT 1
SELECT MAX(sal) FROM emp #获取sal这列里的最大值
#求最低薪min
SELECT sal FROM emp ORDER BY sal LIMIT 1
SELECT MIN(sal) MIN FROM emp
#求和sum
SELECT SUM(sal) FROM emp
#求平均数avg
SELECT AVG(sal) FROM emp
SELECT MAX(sal),MIN(sal),SUM(sal),AVG(sal)
FROM emp
#求总个数count
SELECT COUNT(comm) FROM emp#不统计comm字段值是null的-低效
SELECT COUNT(*) FROM emp#都统计
SELECT COUNT(1) FROM emp#都统计-高效
#统计工资>8000的人数
SELECT COUNT(1) FROM emp
WHERE sal>8000
#统计2019年入职的人数
SELECT COUNT(1) FROM emp
WHERE YEAR(hiredate)=2019
六,分组
–1,测试
#什么时候必须分组?当查询结果中出现了聚合列和非聚合列时
#按照什么分组合理?通常按照非聚合列分组
#什么是聚合列非聚合列?使用了聚合函数max min sum avg count的就是聚合列
#统计每个部门的平均薪资
SELECT deptno,AVG(sal) FROM emp
GROUP BY deptno #按照部门编号分组
#统计每个岗位的最高薪资
SELECT MAX(sal),job FROM emp
GROUP BY job#按照岗位分组
#统计每年的入职人数
#count是聚合函数,year只是普通函数
SELECT COUNT(1),YEAR(hiredate) FROM emp
GROUP BY YEAR(hiredate)#按照非聚合列分组
#having的作用:用来对分组后的数据,进一步过滤
#统计每个部门的平均薪资,只要>10000的记录
SELECT deptno,AVG(sal) FROM emp
GROUP BY deptno
HAVING AVG(sal)>10000
#统计每个岗位的最高薪资,只要>8000的记录
SELECT job,MAX(sal) FROM emp
#先过滤再分组高效,但是where里不能用聚合函数
#where MAX(sal)>8000 #会报错
GROUP BY job
HAVING MAX(sal)>8000
ORDER BY MAX(sal) #升序排序
#统计每年的入职人数,只要人数>1的记录
SELECT COUNT(1),YEAR(hiredate) FROM emp
GROUP BY YEAR(hiredate)
HAVING COUNT(1) > 1
#不能改成where,后面出现了聚合函数
#统计每年的入职人数,只要2017年以后的记录
SELECT COUNT(1),YEAR(hiredate) FROM emp
WHERE YEAR(hiredate) > 2017 #高效,只是where里不能出现聚合函数
GROUP BY YEAR(hiredate)
#having YEAR(hiredate)> 2017
#having里使用的过滤条件必须是查到的结果
七,事务
-1,概述
保证SQL语句,要么全执行成功,要么全失败
有四个特征ACID:
A是原子性: 是指多条SQL是一个原子,密不可分.如果都正确,就操作了数据.如果有错误的都会发生回滚,回到事务执行之前.
C是一致性: 保证了数据的一致性和完整性.
I是隔离性: 保证多线程并发时的数据安全,多个操作之间是被隔离的.
D是持久性: 是指对数据CDU的影响是持久生效的.
隔离级别:读未提交 读已提交 可重复读 串行化
从前往后,性能越来越差,安全性越来越高.MySQL默认是可重复读
-2,测试
先开启事务,然后执行一批SQL,再结束事务
mysql> start transaction; #开启事务
Query OK, 0 rows affected (0.00 sec)
mysql> insert into dept values(18,'java','shanghai');
Query OK, 1 row affected (0.00 sec)
mysql> insert into dept values(19,'java2','shanghai2');
Query OK, 1 row affected (0.00 sec)
mysql> commit; #提交事务
Query OK, 0 rows affected (0.03 sec)
八,字段约束
–1,默认约束和检查约束
#默认约束:给指定字段设置默认值
CREATE TABLE f(
id INT PRIMARY KEY AUTO_INCREMENT,#主键,自动递增
sex VARCHAR(10) DEFAULT '男' #设置默认值
)
#检查约束:给指定字段设置合法值的检查规则
CREATE TABLE g(
id INT PRIMARY KEY AUTO_INCREMENT,#主键,自动递增
age INT,
CHECK(age>0 AND age<200)#设置检查
)
–2,外键约束
#默认约束:给指定字段设置默认值
CREATE TABLE f(
id INT PRIMARY KEY AUTO_INCREMENT,#主键,自动递增
sex VARCHAR(10) DEFAULT '男' #设置默认值
)
#检查约束:给指定字段设置合法值的检查规则
CREATE TABLE g(
id INT PRIMARY KEY AUTO_INCREMENT,#主键,自动递增
age INT,
CHECK(age>0 AND age<200)#设置检查
)
#外键:通过指定的SQL语句描述了两张表的关系
#约束:子表添加记录时id必须在取自主表
#删除主表记录时,必须没有被子表使用着
#怎么确定谁是子表谁是主表?子表中有外键的SQL
CREATE TABLE tb_user(
id INT PRIMARY KEY AUTO_INCREMENT,
NAME VARCHAR(10),
sex VARCHAR(10)
)
CREATE TABLE tb_user_address(
user_id INT PRIMARY KEY AUTO_INCREMENT,
address VARCHAR(20),
#表明和哪张表的哪个字段有关系
#foreign key(本表的主键) references 关联表(主键)
FOREIGN KEY(user_id) REFERENCES tb_user(id)
)
九,索引
一、索引
MySQL索引的建立对于MySQL的高效运行是很重要的,索引可以大大提高MySQL的检索速度。
打个比方,如果合理的设计且使用索引的MySQL是一辆兰博基尼的话,那么没有设计和使用索引的MySQL就是一个人力三轮车。
索引分单列索引和组合索引。单列索引,即一个索引只包含单个列,一个表可以有多个单列索引,但这不是组合索引。组合索引,即一个索引包含多个列。
创建索引时,你需要确保该索引是应用在 SQL 查询语句的条件(一般作为 WHERE 子句的条件)。
实际上,索引也是一张表,该表保存了主键与索引字段,并指向实体表的记录。
上面都在说使用索引的好处,但过多的使用索引将会造成滥用。因此索引也会有它的缺点:虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存一下索引文件。
建立索引会占用磁盘空间的索引文件。
二、索引类型
Mysql目前主要有以下几种索引类型:FULLTEXT,HASH,BTREE,RTREE。
1. FULLTEXT
即为全文索引,目前只有MyISAM引擎支持。其可以在CREATE TABLE ,ALTER TABLE ,CREATE INDEX 使用,不过目前只有 CHAR、VARCHAR ,TEXT 列上可以创建全文索引。
全文索引并不是和MyISAM一起诞生的,它的出现是为了解决WHERE name LIKE “%word%"这类针对文本的模糊查询效率较低的问题。
2. HASH
由于HASH的唯一(几乎100%的唯一)及类似键值对的形式,很适合作为索引。
HASH索引可以一次定位,不需要像树形索引那样逐层查找,因此具有极高的效率。但是,这种高效是有条件的,即只在“=”和“in”条件下高效,对于范围查询、排序及组合索引仍然效率不高。
3. BTREE
BTREE索引就是一种将索引值按一定的算法,存入一个树形的数据结构中(二叉树),每次查询都是从树的入口root开始,依次遍历node,获取leaf。这是MySQL里默认和最常用的索引类型。
4. RTREE
RTREE在MySQL很少使用,仅支持geometry数据类型,支持该类型的存储引擎只有MyISAM、BDb、InnoDb、NDb、Archive几种。
相对于BTREE,RTREE的优势在于范围查找。
ps. 此段详细内容见此片博文:Mysql几种索引类型的区别及适用情况
三、索引种类
普通索引:仅加速查询(MySQL中基本索引类型,没有什么限制,允许在定义索引的列中插入重复值和空值,纯粹为了查询数据更快一点。)
唯一索引:加速查询 + 列值唯一(可以有null)
主键索引:加速查询 + 列值唯一(不可以有null)+ 表中只有一个。
组合索引:多列值组成一个索引,专门用于组合搜索,其效率大于索引合并。(在表中的多个字段组合上创建的索引,只有在查询条件中使用了这些字段的左边字段时,索引才会被使用,使用组合索引时遵循最左前缀集合。例如,这里由id、name和age3个字段构成的索引,索引行中就按id/name/age的顺序存放,索引可以索引下面字段组合(id,name,age)、(id,name)或者(id)。如果要查询的字段不构成索引最左面的前缀,那么就不会是用索引,比如,age或者(name,age)组合就不会使用索引查询)
全文索引:只有在MyISAM引擎上才能使用,只能在CHAR,VARCHAR,TEXT类型字段上使用全文索引,介绍了要求,说说什么是全文索引,就是在一堆文字中,通过其中的某个关键字等,就能找到该字段所属的记录行,比如有"你是个大煞笔,二货 ..." 通过大煞笔,可能就可以找到该条记录。这里说的是可能,因为全文索引的使用涉及了很多细节,我们只需要知道这个大概意思。
ps:索引合并,使用多个单列索引组合搜索;
覆盖索引,select的数据列只用从索引中就能够取得,不必读取数据行,换句话说查询列要被所建的索引覆盖。
聚集(clustered)索引:也叫聚簇索引,是指数据行的物理顺序与列值(一般是主键的那一列)的逻辑顺序相同,一个表中只能拥有一个聚集索引。MySQL中一般默认主键为聚集索引。
非聚集(unclustered)索引:该索引中索引的逻辑顺序与磁盘上行的物理存储顺序不同,一个表中可以拥有多个非聚集索引。其实按照定义,除了聚集索引以外的索引都是非聚集索引,只是人们想细分一下非聚集索引,分成普通索引,唯一索引,全文索引。
好处: 大大的提高了SQL的查询效率
坏处: 索引本身也是一张表,表里的数据和真正的表里的数据是重复的,浪费了空间.
操作索引的命令:
查看索引:SHOW INDEX FROM emp
#索引的分类:单值/唯一/复合
#1.创建 单值索引:一个索引包含了一个列
CREATE INDEX job_index ON emp(job)
#创建 唯一索引
#alter table emp add unique(deptno)报错,deptno的值重复啦
ALTER TABLE emp ADD UNIQUE(ename)
#创建 复合索引:最左特性
ALTER TABLE emp ADD INDEX many_index(ename,job,hiredate)
#2.查看索引
SHOW INDEX FROM emp
#3.使用索引
EXPLAIN
#用来观察SQL的执行计划,主要看有没有用索引
#(观察两列的结果:key和possible_keys)
SELECT * FROM emp WHERE job='经理'#背后会用job索引
EXPLAIN
SELECT * FROM emp WHERE empno=100#背后会用主键索引
EXPLAIN
SELECT * FROM emp WHERE ename='jack'#背后会用唯一索引
SELECT * FROM emp WHERE ename='jack' AND job='经理'#复合索引生效
SELECT * FROM emp WHERE hiredate='2010-1-1'#复合索引失效
SELECT * FROM emp WHERE job='经理' AND hiredate='2010-1-1'#复合索引失效
十,关联查询
–1,测试
#多表联查:一张表已经无法满足业务需求,需要联合查询多张表
#方式1:笛卡尔积
SELECT * FROM dept,emp #查出了所有数据
SELECT * FROM dept,emp
#表名.字段名
WHERE dept.deptno=emp.deptno#两张表的关联关系
AND dept.dname='accounting'
#方式2:连接查询join
#inner join/left join/right join
#工作中,常用的是: 小表 left join 大表,小表驱动大表
SELECT * FROM emp
#inner join dept #两边都满足的交集
LEFT JOIN dept #左边的所有和右边满足了的
#right JOIN dept #右边的所有和左边满足了的
ON dept.deptno=emp.deptno #描述字段
WHERE dept.dname='accounting' #具体过滤条件
#方式3:子查询:把上次的查询结果作为条件再次查询
#1.根据部门名称查部门编号dept
SELECT deptno FROM dept WHERE dname='accounting'
#2.把查到的编号作为条件,查员工信息emp
SELECT * FROM emp WHERE deptno=1
#查询部门名称是accounting的所有信息
SELECT * FROM emp WHERE deptno=(
SELECT deptno FROM dept WHERE dname='accounting'
)