数据库的基础知识介绍完了,下面介绍的是在开发过程要需要注意的知识点,这样对提高数据库的性能十分重要!

1.表类型(存储引擎)的选择

InnoDB

InnoDB存储引擎提供了具有提交、回滚和崩溃恢复能力的事务安全。但是对比与MyISAM的存储引擎,InnoDB写的处理效率 差一些,并且会占用更多地磁盘空间以保留数据和索引。

InnoDB不同于其他存储引擎的表的特点:

  • 自动增长列:InnoDB表的自动增长列可以手工插入,但是如果是插入的值是空或者是0,则实际插入的将是自动增长后的值。通过ALTER TABLE *** AUTO_INCREMENT = n 语句强制设置自动增长列的初始值,默认从1开始,但是该强制的默认值是保留在内存中的,如果该值在使用之前数据库重新启动,那么该值会失效。对于InnoDB表,自动增长列是索引,如果是组合索引,也必须是组合索引的第一列
  • 外键约束:MySQL支持外键的存储引擎只有InnoDB,在创建外键的时候,要求父表必须有对应的索引,子表在创建外键的时候也会自动创建对应的索引。
  • 存储方式:InnoDB存储表和索引有以下两种存储方式1.使用共享表空间2.使用多表空间存储(多表空间存储可以比较方便进行单表备份和恢复操作,共享表空间存储InnoDB把内部数据词典和在线重做日志放在这个文件中)

1.1MySQL中Myisam与Innodb的区别,至少5点:

一、5点不同:

  • 1、InnoDB支持事务,而MyISAM不支持事务。
  • 2、InnoDB支持行级锁,而MyISAM不支持行级锁。
  • 3、InnoDB支持MVCC,而MyISAM不支持。
  • 4、InnoDB支持外键,而MyISAM不支持。
  • 5、InnoDB不支持全文索引,而MyISAM支持。

二、InnoDB引擎的4大特性

  • 1、插入缓冲(insert buffer)
  • 2、二次写(double write)
  • 3、自适应哈希索引(ahi)
  • 4、预读(read ahead)

三、、2者select count(*)哪个更快,为什么

myisam更快,因为myisam内部维护了一个计数器,可以直接调取。

2.选择合适的数据类型

在项目中创建一个表时,需要为各个属性值定义数据类型,通常我们很少考虑到如何选择合适的数据类型,导致查询的速度慢的问题,下面介绍不同数据类型的差别。

CHAR与VARCHAR

charvarchar类型相似,都是用来存储字符串的,但是它们保存检索的方式不同。char属于固定长度的字符类型,varchar是属于可变长度的字符类型。

char(4) 存储需求 varchar(4) 存储需求(非严格模式)
'' ' ' 4个字节 '' 1个字节
‘ab’ ‘ab ' 4个字节 ‘ab’ 3个字节
‘abcd’ ‘abcd’ 4个字节 ‘abcd’ 5个字节
‘abcdefgh’ ‘abcd’ 4个字节 ‘abcd’ 5个字节

总结:固定长度使用char比较好,缺点是浪费存储空间,但是总的来说,char的平均占用时间多余varchar,一般是使用varchar。

TEXT与BLOB

一般在保存少量的字符串的时候,我们会选择使用char或者varchar;而在保存较大文本是,通常会选择使用text或者blob。二者之间的差别是blob能用来保存二进制数据,比如照片;而text只能保存字符数据,比如一篇文章或者日记。

常见问题分析:

  • blob和text值会引起一些性能问题,特别是在执行了大量的删除操作时。删除操作会在数据表中留下很大的空洞,以后填入这些空洞的记录在插入的性能会有影响。为了提高性能,建议定期使用optimize table功能对这类表进行碎片整理。
  • 可以使用合成的(Synthetic)索引来提高大文本字段的查询性能。(简单的来说,合成索引就是根据大文本字段的内容建立一个散列值,并把这个值存储在单独的数据列中,接下来就可以通过检索散列值找到数据行了)
  • 在不必要的时候避免检索大型的blob或text值。
  • 把blob或text列分离到单独的表中。

浮点数和定点数

浮点数一般用于表示含有小数部分的数值,而定点数实际上是以字符串形式存放的,所以定点数可以更精确的保存数据。如果实际插入的数据精度大于实际定义的精度,则MySQL会进行警告,但是数据还是按照实际精度四舍五入后插入。

3.索引的设计和使用

3.1 什么是索引?

索引是对数据库表中一或多个列的值进行排序的结构,是帮助MySQL高效获取数据的数据结构。索引就是加快检索表中数据的方法。

例如:这样的一个查询select * from t_measure_data where update_timestamp ='1475045438'; 。如果没有索引,必须遍历整个表,直到update_timestamp的这一行被找到为止;有了索引之后(必须是在update_timestamp 这一列建立的索引),即可在索引中查找。由于索引是经过某种算法优化过的,因而查找次数要少的多。可见,索引插叙的速度要比没有索引的速度要快很多。

下面进行一个查询时间的对比:

没有建立索引:

image.png

建立索引后:

1524901607281.png

很明显,建立索引后的查询速度是很快的。

3.2 索引的原理

索引(index)是帮助MySQL高效获取数据的数据结构。InnoDB存储引擎的表默认创建的是BTree索引。请看MySQL的Btree索引原理

3.3 索引的类型

从逻辑角度,索引可以分为以下几种:

  • 1、普通索引:最基本的索引,它没有任何限制。
1
create index 索引名称 on 表名(列名)
  • 2、唯一索引:唯一性索引unique index和一般索引normal index最大的差异就是在索引列上增加了一层唯一约束。添加唯一性索引的数据列可以为空,但是只要存在数据值,就必须是唯一的。
1
create unique index 索引名 on 表名(列名)
  • 3、主键索引:它是一种特殊的唯一索引,用于唯一标识数据库中的某一条记录,不允许有空值,一般使用Primary Key来约束。
1
alter table 表名 add primary key;
  • 4、联合索引(复合索引):多个字段上建立的索引,能够加速复合查询条件的检索。
1
2
3
4
5
create index S_Sno_Sname on Student(Sno,Sname);
#建立这样的组合索引,其实是相当于分别建立了下面两两组合索引
-Sno,Sname
-Sno
#为什么没有Sname这样的组合索引?这是因为MySQL组合索引“最左匹配原则”
  • 5、全文索引: MySQL 自带的全文索引只能用于数据库引擎为 MyISAM 的数据表,新版本 MySQL 5.6 的 InnoDB 支持全文索引。默认 MySQL不支持中文全文检索,可以通过扩展 MySQL,添加中文全文检索或为中文内容表提供一个对应的英文索引表的方式来支持中文。

3.4 设计索引的基本原则

索引的设计可以遵循一些已有的原则,创建索引的时候请尽量考虑符合这些原则,便于提高索引的使用效率,更有效的使用索引。

  • 搜索的索引列,不一定是要选择的列。换句话说,最合适索引的列是出现在where字句中的列,或连接子句中指定的列,而不是出现在select关键字后的选择列表中的列。

  • 使用唯一列。考虑某列中值的分布,索引的列的基数越大,索引的效果越好。

  • 使用短索引。如果对字符串列进行索引,应该指定一个前缀长度,只要有可能就应该这样做。

  • 利用最左前缀(组合索引)。组合索引可以更好的提高MySQL效率,最左索引遵循"最左索引"原则。创建符合索引时应该将最常用(频率)作限制条件的列放在最左边,依次递减

  • 不要过度索引。每个额外的索引都要占用额外的磁盘空间,并降低些操作的性能。

  • 对于InnoDB存储引擎的表,记录默认会按照一定的顺序保存,如果有明确定义的主键,则按照主键顺序保存。

下面介绍一下建立索引的字段和时机:

image

创建索引

索引在创建表的时候可以同时创建,也可以随时增加新的索引。创建新索引的语法为:

1
create [unique\fulltext\spatial] index index_name [using index_type] on tbl_name(index_clo_name...)

image.png

修改索引

在MySQL中并没有提供修改索引的直接指令,一般情况下,我们需要先删除掉原索引,再根据需要创建一个同名的索引,从而变相地实现修改索引操作。

1
2
3
4
#先删除
ALTER TABLE user DROP INDEX idx_user_username;
#再修改后内容创建同名索引
CREATE INDEX idx_user_username ON user (username(8));

删除索引

索引的删除语法为:

1
drop index index_name on tbl_name
1
2
#想要删除Student表上的索引Stusno
drop index Stusno on Student;

image.png

查看索引

1
show index from Student\G

image.png

索引的优化

索引的好处很多,但是过多的使用索引将会造成滥用。因此索引也会有它的缺点:

  • 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT、UPDATE和DELETE。因为更新表时,MySQL不仅要保存数据,还要保存索引文件。
  • 建立索引会占用磁盘空间的索引文件。

了解MySQL的优化:MySQL优化那些事儿

4.视图

什么是视图

视图(View)是一种虚拟存在的表,对于使用视图的用户来说基本是透明的。视图并不在数据库汇总实际存在,行和列数据来自定义视图的查询中使用的表,并且是在使用视图时动态生成的。

视图的作用

从用户角度来看,一个视图是从一个特定的角度来查看数据库中的数据。从数据库系统内部来看,一个视图是由SELECT语句组成的查询定义的虚拟表。从数据库系统内部来看,视图是由一张或多张表中的数据组成的,从数据库系统外部来看,视图就如同一张表一样,对表能够进行的一般操作都可以应用于视图,例如查询,插入,修改,删除操作等。

在经常用到的查询或者复杂的多表查询、权限限制的时候使用视图比较好什么时候使用视图

视图相对于普通表的优势主要包括以下几点:

  • 简单:使用视图的用户完全不需要关心后面对应的表的结构、关联条件和筛选条件,对用户来说已经是过滤好的符合条件的结果集。
  • 安全:使用视图的用户只能访问他们被允许查询的结果集,对表的权限管理并不能限制到某个列某个行,但是通过视图就可以简单的实现。
  • 数据独立:一旦视图的结构确定了,可以屏蔽表结构变化对用户的影响,源表增加列对视图没有影响;源表修改列名,则可以通过修改视图来解决,不会造成对访问者的影响。

视图操作

视图的操作包括创建或者修改视图、删除视图以及查看视图定义

创建或者修改视图

创建视图的语法为:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
create [or replace][algorithm={undefined\merge\temptable}]
view view_name[(column_list)]
as select_statement
[with [cascaded\local] check option]

#payment表创建视图
create or replace view payment_view as 
select payment_id,amount from payment
where amount < 10 
with check option 

修改视图的语法为:

1
2
3
4
alter [algorthm={undefined\merge\temptable}]
view view_name[(column_list)]
as select_statement
[with [cascaded\local] check option]

删除视图

用户可以一次删除一个或者多个视图,前提是必须有该视图的drop权限。

1
2
3
4
drop view [if exists] view_name [,view_name]... [restrict|cascade] 

#删除staff_list视图
drop view staff_list

查看视图

1
2
3
4
5
#show tables不仅显示表的名字,同时也显示视图的名字
show tabels
show tabels status [from db_name] [like 'pattern']
#查看staff_list视图信息
show table status like 'staff_list' \G

更新视图

更新视图时,可以先用drop再用create,也可以直接用create or replace view。

如果视图定义中有以下操作,怎不能进行视图的更新:

  • 分组(使用group by和having)
  • 联结
  • 子查询
  • 聚集函数(Min()、Count()、Sum())等
  • distinct
  • 导出(计算)列

理解视图的例子(例3.86)

1
2
3
4
5
Create view IS_S1 (Sno,Sname,Grade)
as
select Student.Sno,Sname,Grade
from Student,SC
where Sdept='CS' and Student.Sno = SC.Sno and SC.Cno ='1' ;

建立信息系选修了1号课程的学生的视图(包括学号、姓名、成绩)。

现在,假如可以把整个查询包装成一个名为IS_S1的虚拟表,则可以如下轻松的检索出相同得数据:

1
select * from IS_S1;

这就是视图的作用。IS_S1是一个视图,作为视图,它不包含表中应该有的任何列或数据,它包含的是一个SQL查询(与上面用以正确联结表的相同的查询)。

image.png

视图提供了一种MySQL的select语句层次的封装,可用来简化数据处理以及重新格式化基础数据或者保护基础数据。