9大表设计优化方法,让 MySQL 性能飞升!

表设计优化,是 MySQL 调优中至关重要的一个环节,也是大厂高频面试题之一。

一个优秀合理的表设计优化,可以有效地减少线上问题,极大地提升 MySQL 的性能和稳定性

本文主要介绍 9 个常用的优化表设计方法。

01

避免深分页 

从 MySQL 中查询大量数据时,可以使用分页来避免一次性返回大量的数据。

但如果分页深度太深,就会影响 MySQL 的性能。因此,要避免深分页,保证每一页的数据量不要过多。

例如:

有一个用户表,里面存储了 1000 万条用户记录。

需要在网页上显示第 10000-10020 条记录,可以使用如下SQL 查询:

SELECT * FROM users LIMIT 10000, 20;

需要显示第 9999990-10000010 条记录,可以使用如下 SQL 查询:

SELECT * FROM users LIMIT 9999990, 20;

这个时候,MySQL 要扫描 9999990 条记录才能返回结果,这就严重影响到了 MySQL 的性能。

02

单表字段不要超过30个 

在设计表结构时,避免将过多的字段存储在单个表中。

如果一个表中的字段太多,可能会导致 MySQL 性能下降、工作量增加。

例如:

有一个用户表,需要存储用户的基本信息、订单信息、收货地址等信息。

我们可以将用户信息、订单信息、收货地址信息分别存储在 3 个表中,通过关联键进行关联,而不是将这些信息全部存储在一个表中。

03

枚举字段不要使用字符类型 

枚举字段通常是指一种具有预定义取值集合的字段类型

在 MySQL 中,枚举字段通常被用于表示某个字段只有固定几个值可选的情况。

如果使用字符类型来代替枚举类型去实现类似的功能,会导致存储空间浪费、查询性能降低。

使用字符类型带来的问题:

1)占用更多的存储空间

使用字符类型来存储枚举字段会占用更多的存储空间,尤其是在该字段有大量取值时。

2)查询效率低下

使用字符类型的枚举字段,由于需要对字符类型进行比较,因此查询效率通常会比使用真正的枚举类型要低。

那么,如何使用真正的枚举类型呢?

1)使用 ENUM 类型

ENUM 类型是 MySQL 中的一种列类型,它允许列的值为预定义的值之一。

使用 ENUM 类型可以确保列的值只能是预定义的值,而且存储空间比字符类型要小。

2)避免定义过多的取值

枚举字段的取值不应该太多,一般建议在 5 个以内。否则,枚举类型的性能优势就会丧失。

3)避免在 WHERE 子句中使用枚举类型

枚举类型在 WHERE 子句中使用时,需要将枚举值转换为整数进行比较,这会影响查询效率。

示例:使用 ENUM 类型来存储枚举字段。


CREATE TABLE orders (
    id INT PRIMARY KEY,
    status ENUM('pending', 'approved', 'rejected') NOT NULL,
    customer_id INT NOT NULL,
    order_date DATE NOT NULL,
    amount DECIMAL(10,2) NOT NULL
);

在这个示例中,orders 表中的 status 列只能取三个值之一:pending、approved、rejected。

使用ENUM类型,可确保列的值只能是预定义的值之一,存储空间也要比字符类型小。

综上所述:

当需要使用枚举类型时,尽可能使用 ENUM 类型。这样既避免了存储空间的浪费,同时又提高了查询性能。

04

小数类型禁止使用 float 和 double  

在 MySQL 中,小数类型包括 float、double、decimal。

虽然 float 和 double 可以存储比 decimal 更大的数值,但它们的精度问题可能会导致计算结果出错。

在实际开发中,为了保证计算结果的精度,通常避免使用 float 和 double 类型,并且尽可能使用 decimal 类型。

例如:

假设我们需要计算一个商品的折扣价,可以使用以下 SQL 语句:

SELECT price * discount FROM product;

如果 price 是 float 类型,discount 是 double 类型,那么计算结果就可能出错。

因此,我们应该将 price 和 discount 都设置为 decimal 类型。

05

所有字段必须设置默认值、并且不允许为 null 

在 MySQL 中,字段可以设置默认值和是否允许为 null 。

如果一个字段没有设置默认值,而且允许为 null,那么在插入数据时,如果不显式地指定该字段的值,那么该字段的值就会是 null,这可能导致数据错误或逻辑混乱。

正确的操作是,将所有的字段都设置默认值,并且不允许为null。

如果一个字段没有设置默认值,那么我们可以设置一个合理的默认值,以免在插入数据时出现错误。如果一个字段必须允许为 null,那么就要在应用程序中进行合理的判断,避免出现 null 值。

例如:

假设有一个 user 表,其中包括 id、name 、age 字段,可以使用以下 SQL 语句创建该表:

CREATE TABLE user (
  id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  name VARCHAR(50) NOT NULL DEFAULT '',
  age TINYINT UNSIGNED NOT NULL DEFAULT 0
) ENGINE=InnoDB;

在这个表中:

id 字段设置为主键,并且不允许为 null 。

name 字段和 age 字段都设置了默认值,并且不允许为 null。

这样,在插入数据时,如果不显式地指定 name 和 age 字段的值,那么它们的值就会是默认值。

06

必须创建主键,最好是有序数值类型 

主键是用来唯一标识表中每行数据的一列或一组列。

通过主键,可以很方便地进行数据的增删改查操作,同时提高查询效率。在设计表结构时,应该为每个表都定义一个主键。

在选择主键列时,尽量选择有序数值类型。这样可以保证每个新插入的记录的主键值是递增的,这种方式被称为自增主键

自增主键的优点是:可以极大地提高插入新记录的效率,并且避免主键冲突的问题。

示例:

创建自增主键


CREATE TABLE users (
  id INT(11) NOT NULL AUTO_INCREMENT,
  username VARCHAR(50) NOT NULL,
  email VARCHAR(100) NOT NULL,
  password VARCHAR(255) NOT NULL,
  PRIMARY KEY (id)
);

在上面的示例中,id 列被设置为自增主键,并且被定义为整数类型。

这样,在每次插入新记录时,MySQL 会自动为 id 列赋一个递增的值,从而保证了每个新记录的主键值都是唯一的。

需要注意的是:

  • 在创建表时,应该始终为每个表定义一个主键。

  • 如果没有显式定义主键,MySQL 可能会选择默认的主键,这可能会导致性能问题。

  • 同时,在选择主键列时,应该选择简单、唯一、递增的列。

07

 in 条件中数量不宜过多 

在开发过程中,我们经常会使用 IN 语句来查询多个值。

在使用 IN 语句时:

  • 尽可能减少 IN 语句中包含的值的数量

  • 如果需要查询多个值,可以考虑使用多个 OR 条件来替代 IN 语句

这是因为:

如果 IN 语句中包含的值过多,MySQL 将这些值全部加载到内存中,然后进行匹配,这样就会导致查询变慢。如果值的数量很大,内存占用过高,一旦超出了系统的内存限制,就会引发数据库崩溃。

示例:

使用 IN 语句来查询一组特定的数据,例如查询某个部门中一组特定的员工信息。

SELECT * FROM employees WHERE department_id IN (1, 2, 3, 4, 5);

当 IN 语句中包含大量的值时,查询的效率就会急剧下降,这是因为 MySQL 会逐一比较每个值,消耗大量的 CPU 和内存资源,造成查询变慢。

所以,如果在 IN 语句中包含大量的值时,需要考虑使用其他的查询方式。

常见的优化方法是将 IN 语句替换成 EXISTS 子查询。例如:

EXISTS (SELECT 1 FROM department d WHERE e.department_id = d.id AND d.id IN (1, 2, 3, 4, 5));

这个查询会返回与之前相同的结果,但查询效率更高了。这是因为 MySQL 会优先执行 EXISTS 子查询,判断某个部门是否存在于指定的 ID 列表中,如果存在,再去查询员工信息。

除了使用 EXISTS 子查询外,还有其他一些优化 IN 语句的方法:将 IN 语句中的值转换为临时表,然后进行 JOIN 操作;又或者使用多个 OR 条件替代 IN 语句。

但是,这些方法并不是适用于所有情况,还是要根据实际情况来选择最合适的方法。

08

禁止创建预留字段 

在数据库设计中,预留字段是指为将来可能需要而设置的字段,但目前并没有实际用途的字段。

预留字段的缺点

  • 预留字段看起来有助于扩展数据结构,实则增加了表的宽度,浪费存储空间,并降低查询性能。

  • 预留字段的使用,可能增加代码复杂性,在开发时就要去考虑这些字段在未来的应用,甚至更改表结构,将投入大量时间和精力来处理数据迁移、以及其他相关问题。

因此,禁止创建预留字段,在需要时再添加新字段,这样可以更好地保证数据库的整洁和高效。

09

单表索引数不要超过 5 个 

索引是一种用于加速数据检索的数据结构。

在数据库中,为了提高查询效率,我们通常会在表的字段上创建索引。但是,索引会占用磁盘空间,维护索引也需要时间和资源。如果过度创建索引,将会导致查询变慢。

建议:

  • 在一个表中,不要创建超过 5 个索引

  • 在确定要创建哪些索引时,可以优先考虑常用的查询条件需要频繁更新的字段。例如:如果经常按日期范围查询,则可以在日期字段上创建索引。

  • 在创建索引时,避免在具有大量重复值的列上创建索引,会浪费磁盘空间。

  • 使用索引优化器来确定哪些索引最适合特定查询。索引优化器可以帮助我们避免创建不必要的索引,并确保查询性能的最大化。

本文从深分页、字段数量、字段类型、默认值、主键设计、记录判断、in条件、预留字段和索引数量等多个方面,全面介绍了表设计优化的注意事项和实用经验。

表设计优化是一个综合性的过程,需要从多个角度来考虑。

通过合理的表设计和优化,可以减少我们的开发工作量和线上问题,提升 MySQL 的性能和稳定性。

以上。

9大表设计优化方法,让 MySQL 性能飞升!https://mp.weixin.qq.com/s/0EOj40epd1PumstV7i48gw

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