MySQL字符串类型的字段 默认值NULL、空值、Empty String的区别,哪个更好?

https://file-one.7k7s.com//uploads/20240604/89f56a7378e381410f4dfcfab3948775.jpg
陈杰 案例分析 发布于6个月前 更新于6个月前 492

MySQL默认值NULL、空值、Empty String的区别,哪个更好?

当我们在数据库中添加一个新的字段时,通常会面临选择:应该设置默认值为NULL、空值,还是Empty String(空字符串)?这篇文章将帮助你理解这些选择之间的差异及其影响

三种值的介绍

  1. 空值

    • 空值(空白)通常意味着字段没有被显式设置。当在设计表结构时保存空值,它通常会自动转变为NULL
  2. NULL

    • NULL表示未知或未定义的值。它在数据库中是一个特殊的标记,不等同于空字符串或零。
  3. Empty String

    • Empty String是一个长度为0的字符串,表示字段已被定义为一个空的文本值,即''""

NOT NULL的好处

  1. 节省空间

    • NULL列需要额外的字节来存储是否为NULL的标志位,因此使用NOT NULL可以节省空间。
  2. 减少空指针问题

    • 查询时,可以减少与NULL相关的空指针异常问题。
  3. 减少计算错误

    • 在统计时,NULL值不会被计入,例如COUNT(column)会忽略NULL值,这可能导致意外的结果。

设置为NULL的坏处

  1. 索引效率

    • 含有NULL值的列在查询优化时较困难,索引中不存储NULL值,这可能导致索引效率下降。建议使用0、特殊值或空字符串代替。
  2. 负向条件查询

    • 使用!=NOT IN时,NULL值可能导致查询结果为空,容易引发错误。
  3. 占用空间

    • NULL虽然不占据数据存储空间,但需要额外字节标记,空字符串''不需要这个标记。
  4. 统计问题

    • COUNT()统计时忽略NULL,但不忽略空字符串,这可能导致统计分析误差。
  5. 查询复杂性

    • 在SQL中,判断NULL需要使用IS NULLIS NOT NULL,而空字符串则可以用常规比较操作符。

综上建议

  • 字符串类型字段:推荐设置默认值为空字符串''。这样可以避免NULL带来的复杂性,并确保字段始终有可比较的值。
  • 整数类型字段:建议设置默认值为0。这避免了处理NULL整数值的复杂性,并提供一个明确的初始值。

扩展

在MySQL中,WHERE <column> IS NOT NULL这种查询条件通常会导致全表扫描(full table scan),即使该列上存在索引。这主要是由于以下几个原因:

索引查找和全表扫描的区别

  1. 索引结构

    • 索引是按照特定顺序(如B-Tree)存储的,主要用于高效查找特定值或范围内的值。
    • IS NOT NULL需要查找所有非NULL值,这实际上是一个范围查询,可能分布在整个表的数据页中。
  2. 数据分布

    • IS NOT NULL条件需要遍历所有可能的行以确定非NULL值。这涉及大量随机I/O操作,可能导致性能问题。
    • 即使索引中存储了NULL和非NULL值,但为了查找所有非NULL值,仍然会造成大量随机读写,效率不高。

执行计划

通过查看执行计划(EXPLAIN),我们可以理解MySQL优化器如何处理这种查询。假设我们有如下表结构和索引:

CREATE TABLE users (
    id INT PRIMARY KEY,
    username VARCHAR(255) DEFAULT NULL
);

CREATE INDEX idx_username ON users(username);

使用EXPLAIN查看查询计划:

EXPLAIN SELECT * FROM users WHERE username IS NOT NULL;

通常结果会显示:

+----+-------------+-------+------------+------+---------------+------+---------+------+--------+------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows   | Extra|
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+------+-------+
|  1 | SIMPLE      | users | NULL       | ALL  | idx_username  | NULL | NULL    | NULL | 100000 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+--------+------+-------+

解释

  • type = ALL

    • ALL表示全表扫描。
    • 即使possible_keys显示idx_username为可能使用的索引,但优化器认为全表扫描更有效。
  • rows

    • 估计需要扫描的行数,这个数值较大,表明全表扫描。

为什么全表扫描?

  1. 覆盖范围广

    • IS NOT NULL条件覆盖了所有非NULL值,索引无法有效地利用区间信息进行高效查找。
  2. 数据访问模式

    • 索引通常用于查找特定值或较小范围内的值。
    • 对于大量分布广泛的数据,索引查找效率较低,因为需要多次随机访问数据页。
  3. 优化器选择

    • MySQL优化器基于统计信息选择最优查询方案。
    • 在数据分布和索引效能较差的情况下,全表扫描可能会比索引查找更快。

解决方案

  • 若查询非NULL值频繁且数据量大,可以考虑业务逻辑调整或设计更适合的索引方案。
  • 例如,新增一个标志字段,明确区分NULL和非NULL状态,通过该标志进行查询。

示例改进

ALTER TABLE users ADD COLUMN is_username_not_null TINYINT(1) GENERATED ALWAYS AS (username IS NOT NULL);

CREATE INDEX idx_is_username_not_null ON users(is_username_not_null);

EXPLAIN SELECT * FROM users WHERE is_username_not_null = 1;

这种方式通过增加生成列和索引,优化查询性能。

总结

  • IS NOT NULL条件查询通常会导致全表扫描,即使存在索引。
  • 数据分布、访问模式和优化器选择是主要原因。
  • 根据实际需求设计合适的索引和表结构,可以提高查询性能。
THE END

喜欢就支持一下吧!

版权声明:除却声明转载或特殊注明,否则均为艾林博客原创文章,分享是一种美德,转载请保留原链接,感谢您的支持和理解

不戚戚于贫贱,不汲汲于富贵。

陶渊明

推荐阅读

构建高效稳定的PHP应用:PHP服务器性能优化与架构设计

本文围绕PHP、Linux服务器和前端程序,探讨如何构建高效稳定的PHP应用。文章首先介绍了PHP服务器性能优化的关键步...

https://file-one.7k7s.com//uploads/20240604/89f56a7378e381410f4dfcfab3948775.jpg
陈杰 02月27日

[Mysql] 常用语句汇总

mysql学习教程,集合mysql的入门常见语句语法,包括数据以及服务的操作等

https://file-one.7k7s.com//uploads/20240604/89f56a7378e381410f4dfcfab3948775.jpg
陈杰 03月08日

探索PHP 8:构建更现代、安全和高效的Web应用程序

深入探讨如何使用PHP 8的新特性来构建现代、安全、高效的Web应用程序,包括JIT编译器、属性(Attributes)...

https://file-one.7k7s.com//uploads/20240604/89f56a7378e381410f4dfcfab3948775.jpg
陈杰 03月12日

深入理解 PHP 中的依赖注入与控制反转

本文深入讲解 PHP 中的依赖注入与控制反转,包括技术细节、实战案例,并提供总结与扩展学习建议,帮助开发者提升项目架构能...

https://file-one.7k7s.com//uploads/20240604/89f56a7378e381410f4dfcfab3948775.jpg
陈杰 02月27日

PHP数组创建方法大全

本文详细介绍了PHP中创建数组的各种方法,包括基本数组创建、索引数组、关联数组、多维数组以及使用特定函数如range()...

https://file-one.7k7s.com//uploads/20240604/89f56a7378e381410f4dfcfab3948775.jpg
陈杰 05月23日

PHP 代码优化指南:善用命名参数打造清晰可维护的代码

本文全面解析 PHP 8 引入的命名参数特性,详细介绍其优势、最佳实践与注意事项,并结合实际代码示例,帮助开发者编写更优...

https://file-one.7k7s.com//uploads/20240604/89f56a7378e381410f4dfcfab3948775.jpg
陈杰 12月24日

读懂 Docker:基础概念、实用场景与应用现状

本文详细介绍了 Docker 的概念、用途以及其在当下是否广泛使用的情况,从定义、核心组件阐述 Docker 是什么,列...

https://file-one.7k7s.com//uploads/20240604/89f56a7378e381410f4dfcfab3948775.jpg
陈杰 03月08日

探索实用宝藏网站:提升效率的工具集锦

在这篇文章中,我们将分享一些提升工作效率的宝藏网站,包括AI生成PPT、Markdown在线转HTML、AI在线生成Wo...

https://file-one.7k7s.com//uploads/20240604/89f56a7378e381410f4dfcfab3948775.jpg
陈杰 07月25日