数据库优化的方法

结论

一、表的设计合理化,符合三大范式(3NF)

二、添加适当索引(index) [四种: 普通索引、主键索引、唯一索引unique、全文索引]

三、查询语句的优化

四、数据库的分库分表

五、使用存储过程(模块化编程,可以提高速度)

六、数据库硬件升级

七、使用缓存机制

一、表的设计合理化,符合三大范式(3NF)

数据库满足数据库的三大范式可以避免数据冗余。

简单来说三句话:

1NF、列不可分;

2NF、非主键列完全依赖主键,不存在部分依赖;

3NF、非主键列必须直接依赖主键,不存在传递依赖。

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

考虑这样一个表:【联系人】(姓名,性别,电话) 

如果在实际场景中,一个联系人有家庭电话和公司电话,那么这种表结构设计就没有达到 1NF。要符合 1NF 我们只需把列(电话)拆分,即:【联系人】(姓名,性别,家庭电话,公司电话)。1NF 很好辨别,但是 2NF 和 3NF 就容易搞混淆。

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

考虑一个订单明细表:【OrderDetail】(OrderID,ProductID,UnitPrice,Discount,Quantity,ProductName)。

因为我们知道在一个订单中可以订购多种产品,所以单单一个 OrderID

是不足以成为主键的,主键应该是(OrderID,ProductID)。显而易见

Discount(折扣),Quantity(数量)完全依赖(取决)于主键(OderID,ProductID),而

UnitPrice,ProductName 只依赖于 ProductID。所以 OrderDetail 表不符合 2NF。不符合 2NF

的设计容易产生冗余数据。

可以把【OrderDetail】表拆分为【OrderDetail】(OrderID,ProductID,Discount,Quantity)和【Product】(ProductID,UnitPrice,ProductName)来消除原订单表中UnitPrice,ProductName多次重复的情况。

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

考虑一个订单表【Order】(OrderID,OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity)主键是(OrderID)。

其中 OrderDate,CustomerID,CustomerName,CustomerAddr,CustomerCity

等非主键列都完全依赖于主键(OrderID),所以符合 2NF。不过问题是

CustomerName,CustomerAddr,CustomerCity 直接依赖的是

CustomerID(非主键列),而不是直接依赖于主键,它是通过传递才依赖于主键,所以不符合 3NF。

通过拆分【Order】为【Order】(OrderID,OrderDate,CustomerID)和【Customer】(CustomerID,CustomerName,CustomerAddr,CustomerCity)从而达到 3NF。

二、添加适当索引(index) [四种: 普通索引、主键索引、唯一索引unique、全文索引]

1.应考虑在 where 及 order by 涉及的列上建立索引。

2. 更新非常频繁的字段不适合创建索引。

3. 索引并不是越多越好。

大多数情况下索引能大幅度提高查询效率,但:

①数据的变更(增删改)都需要维护索引,因此更多的索引意味着更多的维护成本

②更多的索引意味着也需要更多的空间 (一本100页的书,却有50页目录?)

三、查询语句的优化

1.避免索引失效导致的全表扫描

应尽量避免在 where 子句中对字段进行 null 值判断。

应尽量避免在 where 子句中使用 != 或 <> 操作符。

应尽量避免在 where 子句中使用 or 来连接条件,如果一个字段有索引,一个字段没有索引。

应尽量符合最左前缀原则。

应尽量避免like查询是以%开头。

具体的可以参考我这篇博客:索引失效的几种情况(MySQL)

2.SQL语句的规范

任何地方都不要使用 select * from t ,用具体的字段列表代替“*”,不要返回用不到的任何字段。

...

四、数据库的分库分表

设置数据库主从复制状态下的读写分离,主库进行更新操作,从库进行查询操作。(可以使用中间件Mycat进行实现)

五、使用存储过程(模块化编程,可以提高速度)

什么是存储过程?

存储过程是对一些sql语句和控制语句的封装,客户端可以通过存储过程的名称对其进行调用。

存储过程分类

返回记录集的存储过程

返回数值的存储过程

行为存储过程(在数据库中的更新和删除操作)

六、数据库硬件升级

七、使用缓存机制

可以使用Redis作为缓存,避免所有请求都落在DB上。

你可能感兴趣的:(数据库优化的方法)