数据库(MySQL)

数据库优化

建表优化

1)数据库范式

第一范式(1NF):强调的是列的原子性,即列不能够再分成其他几列。

如电话列可进行拆分---家庭电话、公司电话

第二范式(2NF):首先是 1NF,另外包含两部分内容,一是表必须有主键;二是没有包含在主键中的列必须
完全依赖于主键,而不能只依赖于主键的一部分。

第三范式(3NF):首先是 2NF,另外非主键列必须直接依赖于主键,不能存在传递依赖。

比如Student表(学号,姓名,年龄,性别,所在院校,院校地址,院校电话)

这样一个表结构,就存在上述关系。 学号--> 所在院校 --> (院校地址,院校电话)

这样的表结构,我们应该拆开来,如下。

(学号,姓名,年龄,性别,所在院校)--(所在院校,院校地址,院校电话)

满足这些规范的数据库是简洁的、结构明晰的;同时,不会发生插入(insert)、删除(delete)和
更新(update)操作异常。

2)数据类型选择

数字类型

Float和double选择(尽量选择float)

区分开TINYINT / INT / BIGINT,能确定不会使用负数的字段,建议添加 unsigned定义

能够用数字类型的字段尽量选择数字类型而不用字符串类型的

字符类型

char,varchar,TEXT的选择:非万不得已不要使用 TEXT 数据类型,定长字段,建议使用 CHAR 类型
(填空格),不定长字段尽量使用 VARCHAR(自动适应长度,超过阶段),且仅仅设定适当的最大长度

时间类型

按选择优先级排序DATE(精确到天)、TIMESTAMP、DATETIME(精确到时间)

ENUM
对于状态字段,可以尝试使用 ENUM 来存放

避免使用NULL字段,很难查询优化且占用额外索引空间

3)字符编码

同样的内容使用不同字符集表示所占用的空间大小会有较大的差异,所以通过使用合适的字符集,可以帮助
我们尽可能减少数据量,进而减少IO操作次数。

1.纯拉丁字符能表示的内容,选择 latin1 字符编码

2.中文可选用utf-8

3.MySQL的数据类型可以精确到字段,所以当我们需要大型数据库中存放多字节数据的时候,可以通过对
不同表不同字段使用不同的数据类型来较大程度减小数据存储量,进而降低 IO 操作次数并提高缓存命中率

Sql优化

1) 只返回需要的数据

a) 不要写SELECT *的语句

b) 合理写WHERE子句,不要写没有WHERE的SQL语句。

2) 尽量少做重复的工作 可以合并一些sql语句

3) 适当建立索引(不是越多越好)但以下几点会进行全表扫描 
a) 左模糊查询’%...’
b) 使用了不等操作符!=
c) Or使用不当,or两边都必须有索引才行
d) In 、not in
e) Where子句对字段进行表达式操作
f) 对于创建的复合索引(从最左边开始组合),查询条件用到的列必须从左边开始不能间隔。否则无效,
复合索引的结构与电话簿类似
g) 全文索引:当于对文件建立了一个以词库为目录的索引(文件大全文索引比模糊匹配效果好)

能在char、varchar、text类型的列上面创建全文索引

MySQL 5.6  Innodb引擎也能进行全文索引

如果列类型是字符串,但在查询时把一个数值型常量赋值给了一个字符型的列名name,那么虽然在name列上
有索引,但是也没有用到。

4) 使用join代替子查询

5) 使用union代替手动创建临时表


索引优化

一、 创建索引,以下情况不适合建立索引
表记录太少
经常插入、删除、修改的表
数据重复且分布平均的表字段

二、 复合索引
如果一个表中的数据在查询时有多个字段总是同时出现则这些字段就可以作为复合索引

索引
索引是对数据库表中一列或多列的值进行排序的一种结构。

优点:
大大加快数据的检索速度
创建唯一性索引,保证数据库表中每一行数据的唯一性
可以加速表和表之间的连接

缺点:
索引需要占物理空间。
当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,
降低了数据的维护速度。

索引分类:
普通索引
create index zjj_temp_index_1 on zjj_temp_1(first_name);
drop index zjj_temp_index_1;

唯一索引,索引列的值必须唯一,但允许有空值
create unique index zjj_temp_1  on zjj_temp_1(id);

主键索引,它是一种特殊的唯一索引,不允许有空值。

组合索引


事务

数据库事务(Database Transaction) ,是指作为单个逻辑工作单元执行的一系列操作,要么完全地执行,
要么完全地不执行。 

四大特征:

(1)原子性
事务必须是原子工作单元;对于其数据修改,要么全都执行,要么全都不执行。

(2)一致性
事务的一致性指的是在一个事务执行之前和执行之后数据库都必须处于一致性状态。事务执行的结果必须是
使数据库从一个一致性状态变到另一个一致性状态。

(3) 隔离性(关于事务的隔离性数据库提供了多种隔离级别)
一个事务的执行不能干扰其它事务。即一个事务内部的操作及使用的数据对其它并发事务是隔离的,并发执行
的各个事务之间不能互相干扰。

(4)持久性
事务完成之后,它对于数据库中的数据改变是永久性的。该修改即使出现系统故障也将一直保持。

在介绍数据库提供的各种隔离级别之前,我们先看看如果不考虑事务的隔离性,会发生的几种问题:

脏读
脏读是指在一个事务处理过程里读取了另一个未提交的事务中的数据。

不可重复读

幻读

幻读和不可重复读都是读取了另一条已经提交的事务,不可重复读重点在于update和delete,而幻读的重点
在于insert。

现在来看看MySQL数据库为我们提供的四种隔离级别:
① Serializable (串行化):可避免脏读、不可重复读、幻读的发生。
② Repeatable read (可重复读):可避免脏读、不可重复读的发生。
③ Read committed (读已提交):可避免脏读的发生。
④ Read uncommitted (读未提交):最低级别,任何情况都无法保证。

在MySQL数据库中默认的隔离级别为Repeatable read (可重复读)。

锁模式包括: 

共享锁:(读取)操作创建的锁。其他用户可以并发读取数据,但任何事物都不能获取数据上的排它锁,直到
已释放所有共享锁。

排他锁(X锁):对数据A加上排他锁后,则其他事务不能再对A加任任何类型的封锁。获准排他锁的事务既能
读数据,又能修改数据。

锁的粒度主要有以下几种类型:
行锁: 粒度最小,并发性最高
页锁:一次锁定一页。25个行锁可升级为一个页锁。
表锁:粒度大,并发性低
数据库锁:控制整个数据库操作

乐观锁:相对悲观锁而言,乐观锁假设认为数据一般情况下不会造成冲突,一般的实现乐观锁的方式就是记录
数据版本。

悲观锁:顾名思义,就是很悲观,每次去拿数据的时候都认为别人会修改,所以每次在拿数据的时候都会
上锁,传统的关系型数据库里边就用到了很多这种锁机制,比如行锁,表锁等,读锁,写锁等,都是在做操作
之前先上锁。

MyISAM、InnoDB区别

MyISAM类型不支持事务处理等高级处理,而InnoDB类型支持。
MyISAM表不支持外键,InnoDB支持
MyISAM锁的粒度是表级,而InnoDB支持行级锁定。
MyISAM支持全文类型索引,而InnoDB不支持全文索引。(mysql 5.6后innodb支持全文索引)
MyISAM相对简单,所以在效率上要优于InnoDB,小型应用可以考虑使用MyISAM。当你的数据库有大量的
写入、更新操作而查询比较少或者数据完整性要求比较高的时候就选择innodb表。
当你的数据库主要以查询为主,相比较而言更新和写 入比较少,并且业务方面数据完整性要求不那么严格,
就选择mysiam表。

mysql常见的问题

什么是数据库事务?

要么全做要么全不做,是不可分割的.事务的开始和结束用户是可以控制的,如果没控制则由数据库默认的划分事务.

(1)原子性

指一个事务要么全执行,要么全不执行.也就是说一个事务不可能执行到一半就停止了.

(2)一致性

(3)独立性

(4)持久性

事务运行成功之后数据库的更新是永久的,不会无缘无故的回滚.

 执行数据库查询时候,如果查询的数据有很多,假设有1000万条,用什么方法可以提高查询效率?在数据库方面
或java代码方面有什么优化办法?

1.在数据库设计方面
(1)建立索引
(2)分区(比如说按时间分区)
(3)选取最适用的字段属性(尽量减少字段宽度和使用固定长度的字段)

2.在数据库I/O方面
(1)增加缓冲区
(2)如果涉及到表的级联,最好不同的表放在不同的磁盘,以增加I/O速度

3.Sql语句方法
(1)优化sql语句,减少比较次数,可用连表查询来代替子查询
(2)限制返回的条目数(mysql用limit)
(3)有外键约束会影响插入和删除性能,如果程序能够保证数据的完整性,那在设计数据库时就去掉外键
(比喻:就好比免检产品,就是为了提高效率,充分相信产品的制造商)

4.在java方面

如果反复使用的查询,可通过preparedstatement,因为他在运行前已经预编译,只要运行就Ok了.

分组:group by 列名 

统计各个部门薪水大于5000的人数

SELECT department , COUNT(money) from employee where money>=5000group by department;

分页:limit ()

select * from table limit 5; --返回前5行 

select * from table limit 0,5; --同上,返回前5行  

select * from table limit 5,10; --返回6-15行

排序:order by 列名 

asc 和desc 不写默认为升序

前者是升序后者是降序

第一步:查出各个部门的对应人数,把这个看做一个新表e1
select e.dep_id,count(name) num from employee e group by dep_id;

什么是数据库的三范式?

第一范式(1NF):字段具有原子性,不可再分。所有关系型数据库系统都满足第一范式

数据库表中的字段都是单一属性的,不可再分。例如,姓名字段,其中的姓和名必须作为一个整体

如果要区分出姓和名,必须设计成两个独立的字段。

第二范式(2NF):第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)
必须先满足第一范式(1NF)。

第二范式(2NF)要求实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的
属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间
是一对多的关系。

第三范式的要求如下:满足第三范式(3NF)必须先满足第二范式(2NF)。简而言之,第三范式(3NF)要求
一个数据库表中不包含已在其它表中已包含的非主关键字信息。

union 与union all的区别

union 在进行表链接后会筛选掉重复的记录,所以在表链接后会对所产生的结果集进行排序运算,删除重复
的记录再返回结果。

union all 则会显示重复结果,只是简单的两个结果合并并返回.所以效率比union高,在保证没有重复数据
的情况下用union all.

select name from table1
union
select name  from table2;

用一条 SQL  语句查询出每门课都大于 80 分的学生姓名 

分析:都大于80,他的反面就是<=80,我们可以先求出所有<=80的姓名,然后取反就可以了 

所以sql语句 select name from student where name not in (select  name from student
 where fenshu <=80);

一个用户表中有一个积分字段,假如数据库中有 100 多万个用户,若要在 多万个用户,若要在每年第一天
凌晨将积分清零,你将考虑什么,你将想什么办法解决 每年第一天凌晨将积分清零,你将考虑什么,你将想
什么办法解决?
alter table drop column score;
alter table add colunm score int;

Class.forName()的作用?

按参数中指定的字符串形式的类名去搜索并加载相应的类,如果该类字节码已经被加载过,则返回代表该字节
码的 Class 实例对象,否则,按类加载器的委托机制去搜索和加载该类,如果所有的类加载器都无法加载到
该类,则抛出 ClassNotFoundException。加载完这个 Class 字节码后,接着就可以使用 Class 字节码
的 newInstance 方法去创建该类的实例对象了。

连接查询

分类:内连接、外连接、自然连接(略)、交叉连接(略)。

内连接

基本语法:左表 [inner] join 右表 on 左表.字段 = 右表.字段;

从左表中取出每一条记录,去右表中与所有的记录进行匹配:匹配必须是某个条件在左表中与右表中相同最终
才会保留结果,否则不保留。

外连接

基本语法: 左表 left/right join 右表 on 左表.字段 = 右表.字段;

left join: 左外连接(左连接), 以左表为主表

right join: 右外连接(右连接), 以右表为主表

以某张表为主,取出里面的所有记录,然后每条与另外一张表进行连接:不管能不能匹配上条件,最终都会
保留。能匹配,正确保留;不能匹配,其他表的字段都置空 NULL。

联合查询

基本语法:

		Select 语句 1
		
		Union [union 选项]
		
		Select 语句 2
		
		……

将多次查询(多条 select 语句), 在记录上进行拼接(字段不会增加),每一条 select 语句获取的字段数
必须严格一致(但是字段类型无关)。

应用:查询同一张表,但是有不同的需求;查询多张表,多张表的结构完全一致,保存的数据也是一样的。

索引

如果说数据库表中的数据是一本书,那么索引就是书的目录。索引能够让我们快速的定位想要查询的数据。

索引的结构:BTree 索引和 Hash 索引。

MyISAM 和 InnoDB 存储引擎:只支持 BTREE 索引, 也就是说默认使用 BTREE,不能够更换。

MEMORY/HEAP 存储引擎:支持 HASH 和 BTREE 索引。

索引的分类:单列索引(普通索引,唯一索引,主键索引)、组合索引、全文索引、空间索引。


数据库引擎

1.InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。

2.如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择
InnoDB 有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择 InnoDB,因为
支持事务的提交(commit)和回滚(rollback)。

MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,
对数据的安全性要求较低,可以选择 MEMOEY。

 

你可能感兴趣的:(数据库(MySQL))