MySQL 视图、索引、外键关联策略
目录
- 视图
- 视图常用操作
- 创建视图的完整语法
- 不可更新的视图
- 索引
- 索引的优缺点
- 常见的几种索引
- 常用的索引操作
- 常见的索引方式
- mysql对使用了索引的sql语句的优化
- 联合索引的最左匹配原则
- 索引的最佳实践
- 哪些字段适合创建索引
- 创建索引的注意点
- sql语句中合理运用索引
- 主键
- 外键关联策略
视图
视图是一张虚表,将查询结果集保存起来,作为视图使用。实际存在的表叫作基本表。
视图的作用
- 提高安全性。grant授权用户只能操作视图,通过视图来操作基本表,可以保护基本表中的数据
- 提高查询性能。视图只是基本表的一部分,查视图比查全表快。尤其是多表查询的时候,查视图一张表比连接多张表查询要快很多
视图常用操作
-- 创建视图,as指定结果集,假设cs系的id是1
create view view_dep_cs as (select * from tb_student where dep_id=1); -- 可以把这个视图作为cs系学生信息表来使用-- 修改视图定义,用新结果集覆盖原来的结果集。如果视图不存在,会自动创建
create or replace view view_dep_cs as (select id,name from tb_student where dep_id=1); -- 从视图查询数据
select * from view_dep_cs where name='chy'; --查询cs系名字是chy的学生-- 删除视图
drop view view_dep_cs;
创建视图的完整语法
create [algorithm=merge] view view_dep_cs as (select * from tb_student where dep_id=1) [with check option] ;
algorithm指定视图执行机制,有3个可选的值
1、merge 合并
不创建临时表,执行时会先用视图定义替换视图名,每次都是操作基本表,并不会提高查询性能,但可以增改删查。
2、temptable 临时表
把结果集保存为临时表,每次操作的都是临时表,可以提高查询性能,但只读,不能增删改。
3、undefined 未定义
不指定algorithm就是undefined,使用数据库设置的默认值,mysql默认使用merge。
如果使用merge,还可以设置一个可选参数:with check option 检查条件。
创建视图时设置了条件where dep_id=1,即视图中的记录都是dep_id=1的。
如果指定了with check option,往视图中插入、更新记录时,都要满足记录的dep_id=1这个条件,否则不执行操作;如果不指定with check option,则不要求dep_id=1。
使用merge时往往要设置with check option。
不可更新的视图
即使使用merge,也不一定可以进行增删改,as指定视图数据来源,如果视图来源中使用了一下任一项,则创建的视图只读(只能查询)、不能增删改
- 聚合函数
- group by子句
- having子句
- distinct关键字
- union运算符
- from来源于多个表或者来源于不可更新的视图
一句话:不是直接来源于一个基本表的视图,则该视图只读、不能更新视图数据。
索引
不使用索引时,要操作某些记录,需要遍历整张表来找到匹配的记录,时间开销大。
索引相当于数据表的目录,根据目录可直接定位到章节,根据索引可直接定位到数据表的记录,无需遍历整张表。
索引的优缺点
- 极大提高了检索速度,尤其是记录数很多的时候(优)
- 索引也是一张表,要占硬盘空间,有额外的空间开销(缺)
- 对基本表进行增改删时会同步到索引(维护索引),有额外的时间、资源开销(缺)
相较于优点,索引的缺点微不足道。
常见的几种索引
- 单值索引:索引中只包含数据表的一列(一个字段)
- 唯一索引:索引中列的值唯一,一般是数据表的主键列
- 联合索引:也叫作符合索引,索引中包含数据表的多个列
- 全文索引:只能对MyISAM引擎的表使用,且索引中的列要是char、varchar、text等文本类型
- 覆盖索引:如果索引中已经包含了查询sql要用到的所有字段,则会直接在索引中进行查询,不再回表。如果不是覆盖索引,则先查索引定位记录在表中的位置,再回表查询。
常用的索引操作
create index index_ts on tb_student(id,name); -- on指定使用哪张表的哪些字段来创建索引。经常使用学号、姓名定位学生(记录),所以使用这2列创建索引show index from tb_student; -- 查看某个表上所有的索引drop index index_ts on tb_student; -- 删除索引
索引、视图都可以在数据库管理工具(比如Navicat)中直接操作。索引是在 “设计表” 中操作的。
常见的索引方式
1、b+树
eg. 以id字段创建索引,假设有7条记录,id 1~7
查找id=7的记录的地址:4 -> 6 -> 7
2、hash 通过hash值直接定位记录位置
eg. 使用id字段建立索引,查找id=7的记录:计算7的hash值 -> 根据hash值直接确定记录在表中的位置。
b+树要一级一级地找,hash直接定位,效率远高于b+树。但一般都是使用b+树,因为大多数存储引擎都支持b+树,hash只有memory存储引擎支持。
mysql对使用了索引的sql语句的优化
mysql会对使用了索引的sql语句进行优化,主要优化点如下
- 自动调整同级别and条件的顺序,把使用了索引的字段放前面,尽量走索引。不要过度依赖于mysql自身的优化,尽量把走索引的条件写在前面。
- 走索引的字段使用in限定范围时,in()中的值可以乱序。
- 如果使用in()的字段走的是唯一索引,且()中只有一个值时,会自动优化为=等值判断。
--eg. username、tel都加了唯一索引, age没加索引--mysql会自动调整同级别and条件的顺序、尽量用到索引、选择合适的索引,用and连接时条件时条件可以乱序
where age>18 and username='xxx'--使用了or后,同级别的条件不会走索引,慎用or--三个字段都不会走索引
where username='xxx' and tel='xxx' or age>18
--三个字段都不会走索引,or左边的()作为整体看待不会走索引,()里面的各字段自然不会走索引
where (username='xxx' and tel='xxx') or age>18
--or所在级别的条件tel、age不会走索引,但username会走索引
where username='xxx' and (tel='xxx' or age>18)--模糊查询尽量使用前缀匹配,只有前缀匹配的模糊查询才会走索引--username会走索引
where username like 'x%'
--以下2种的username都不会走索引
where username like '%x%'
where username like '%xx'
联合索引的最左匹配原则
联合索引的最左匹配原则:使用联合索引时,会从联合索引中最左边的字段向右匹配,直到遇到没有使用到联合索引中的字段,或者遇到<、>、between之类的范围限定。
--eg. username、tel、email三个字段建立联合索引--只会用到联合索引的username字段,没有涉及tel到tel就断了,不会用到联合索引中的email字段
where username='xxx' and email='xxx'--只会用到联合索引的username字段,遇到范围限定like直接断了
where username='xxx' and tel like '%888%' and email='xxx'
索引的最佳实践
使用好索引包括2个方面:设计、建立合理的索引, sql语句中合理运用索引。
哪些字段适合创建索引
- 主键
- 外键
- 频繁作为条件的字段。eg. 经常要用where name=’ ',那就给name字段创建索引
- group by分组使用的字段
- order by排序使用的字段
- 统计(聚合函数)使用的字段
添加主键时,会自动给主键列创建唯一索引(Unique);添加外键时,会自动给外键列创建普通索引(Normal)。
创建索引后,从表中查找匹配的记录时数据库会自动使用合适的索引。
创建索引的注意点
1、记录少的表不必建立索引,一般以1千行记录为界限。
建立索引有额外的空间开销,增改删时维护索引也有额外的时间开销,记录数少时全表扫描的性能相对较高,没有必要创建索引。
2、频繁增改删的字段,维护索引开销大,不适合用于创建索引。
3、区分度低的字段建立索引没有多大意义,尽量选择区分度高(列值重复少)的字段建立索引;列值较长的字段不适合作为索引,就算要作为索引,也尽量只取列值的前缀作为索引。
4、联合索引会覆盖其中包含的单列索引,存在联合索引时再建立其中的单列索引没有意义。
5、联合索引遵循最左匹配原则,设计联合索引时,尽量将最左字段设置为值区分度高、使用频率高的字段。
6、一张表建立的索引不宜太多,一般不超过5个索引。
一张表建立太多的索引,空间占用多,数据库会花费更多的时间在索引的选择上,且增删改需要同时维护几个索引,对性能的影响较大。
7、及时删除废弃的、没有必要的索引,避免维护索引带来的不必要开销。
sql语句中合理运用索引
字段加了索引后,sql语句使用索引时需要注意以下几点
1、数据库字段为字符串类型时,sql语句中该字段的值加不加引号都行,但加了引号才会走索引,不加引号则不会走索引。
--值没有加引号,username加了索引也不会走索引
select ... from user where username=xxx;--username会走索引
select ... from user where username='xxx';
2、where子句中,比较运算符左边的列参与了数学运算,则该列不会走索引;参与了函数调用的列不管是放在比较运算符的哪边,都不会走索引。
--比较运算符>=左边的age参与了数学运算,不会走索引
select ... from user where age-18>=0--可以将数学运算移到右边 (以下2个sql的age都会走索引)
select ... from user where age>=0+18
--或者把要走索引的列移到比较运算符的右边
select ... from user where 0+18<=age
3、使用联合索引时,考虑到最左匹配原则,尽量把条件中联合索引中的字段放在范围限定的前面,且字段顺序尽量与联合索引中的字段顺序保持一致,保证尽可能多的使用联合索引中的字段。
主键
mysql创建表时,如果没有指定主键,且存在 整型+not null+自增 的字段,则该字段必须设置为主键才合法。
mysql允许创建表时不指定主键,未指定主键时mysql会自动把 整型+not null 的字段作为主键,如果不存在这样的字段,InnoDB会自动生成一个隐式主键,这个隐式主键我们看不到。
尽量手动给每个表设置主键,保证主键可控。
外键关联策略
eg. tb_order通过外键user_id关联tb_user的主键id,当update、delete tb_user的id时,如何处理与之对应的tb_order中的记录?
设计外键时,mysql提供了4种外键关联策略
1、RESTRICT 限制(默认)
如果有外键关联了tb_user的id,则tb_user不能删除被关联的记录、不能更新关联记录id字段的值(会报错)。
如果要删除记录、更新id字段的值,需要先切断关联关系,比如先删除tb_order中与之关联的记录、或者把相关记录外键字段的值置为null。
2、CASCADE 级联
删除tb_user中的记录时,会自动删除tb_order中与之关联的记录;修改tb_user中id字段的值时,会自动修改tb_order中与之关联的记录的外键字段的值(同步变化)。
3、NO ACTION 不做处理
删除、更新tb_user中的user_id字段的值时,tb_order中与之关联的记录不作任何处理。此种策略需要存储引擎支持,如果存储引擎不支持,会自动换为RESTRICT。
4、SET NULL 置为NULL
删除tb_user的记录,或者更新id字段的值,会自动将tb_order中与之关联的记录的外键字段的值置为NULL。
这种方式有一个要求:设计tb_order时,外键字段不能用NOT NULL约束。
关联数据的更新、删除逻辑应该由我们在代码中控制,更可控,而非交由数据库自动处理,所以一般不设置外键,或者设置外键后使用 NO ACTION 策略。
MySQL 视图、索引、外键关联策略相关推荐
- JPA关系映射系列一:one-to-one外键关联
2019独角兽企业重金招聘Python工程师标准>>> SpringDataJPA是Spring Data的一个子项目,通过提供基于JPA的Repository极大的减少了JPA作为 ...
- mysql 删除表数据_主外键关联表的数据删除策略
说个题外话,我从来没想过会被拼多多这款软件所魔怔,他的这种社交营销的能力,实在是太强了,在怂恿之下,开始给儿子拼个这个, 各位有空帮砍下,https://w.url.cn/s/AzlPAB9,或者扫下 ...
- mysql 外键关联
mysql 外键关联 什么是外键: 外键是一个特殊的索引,用于关联两个表,只能是指定内容. 如我将新建一个daka的表,然后将此表的class_id 与另外一个class的表的cid字段关联 clas ...
- MySQL如何同时删除主外键关联的两张表中的数据
1. 编写目的 介绍一种方法,解决如下问题:如何同时删除两张相关联的表的记录. 比如说表a的外键fk依赖于表a的id,现在我们需要删除id=5的两条数据. 2. 主要方法 为了简单,推荐更改表a的外键 ...
- MySQL — 外键关联操作
目录 文章目录 目录 MySQL 的外键约束 创建表时定义外键(References,参照) 修改原有表的外键约束 删除外键约束 参考文档 MySQL 的外键约束 注意,MySQL 的 InnoDB ...
- MySQL外键关联(一对多)MySQL连接查询
MySQL外键关联(一对多) 外键说明 什么是外键? 1)表A中有字段(如身份证号)做了主键,表B中也有这个字段(身份证号),这里的身份证号一定来自表A同样字段里的内容,但再B表中身份证号对应id可以 ...
- mysql不能删除外键吗,MySQL不能删除外键约束所需的索引
MySQL不能删除外键约束所需的索引 我需要改变现有的数据库添加一列. 因此我也想更新UNIQUE字段来包含这个新列. 我试图删除当前的索引,但不断收到错误MySQL Cannot drop inde ...
- mysql支持UUID做外键_Mysql中以uuid为外键插入多条数据,怎样实现同一个二级分类外键关联的数据为同一个uuid的值...
打开我的navicat,然后找到我的teacher表,选中它,然后点击菜单栏上32313133353236313431303231363533e4b893e5b19e31333431366237的'd ...
- Mysql中的外键分析(什么是外键,为什么要用外键,添加外键,主外键关联删除)
有一个东西一直在我脑海中是个很烦的东西,但是这东西不搞清楚会阻碍自己的前进.自己做项目demo永远只能用一张表... 所以今天还是学习了下外键希望能够搞明白一些... 百度上搜索外键的作用" ...
- 宋体查询1.mysql数据库复习加强 2.mysql事务触发器 3.mysql 索引外键加强 4.zendstudio 的安装使用 5.svn版本控制器的使用-java教程...
上班之余抽点间时出来写写博文,希望对新接触的朋友有帮助.今天在这里和大家起一学习一下宋体查询 1.mysql数据库温习增强 1,导出mysql数据库里ecshop到d盘 mysqldump 指令和 m ...
最新文章
- WebView宽度自适应
- springboot项目打包部署服务器
- 多标签文本分类 [ALBERT](附代码)
- mysql不需要安装_MySQL免安装版 配置
- npm run dev 在本地调试出现跨域问题解决方法
- 自适应响应式炫酷汽车配件类网站源码 html5高端大气汽车网站织梦模板
- VisualSVN Server 修改用户密码
- X86 CPU特性之(3)-kaiser
- drupal8 表单_Drupal 8如何实现面向未来
- 2021 CVPR | 基于渐进感受局部区域推理的全方位监督点云分割
- 搭建自己的病毒扫描系统clamav-原版教程
- 强制更改wifi名前缀CMCC
- Inno Setup打包的exe程序加上【unins.exe】卸载程序
- 基于javaweb的客户信息管理系统搭建
- Alfa与申威【江南所】
- java即时通讯 开源_java开源即时通讯软件服务端openfire源码构建
- 【程序设计训练】棋盘
- java-php-python--数字相册管理系统-点赞演示2021计算机毕业设计
- notepad++使用一行多个关键字的与搜索,同时搜索多个关键词的或搜索
- 白苹果了怎么办_iOS 13如何降级?iOS13降级失败怎么办?