数据库查询——索引优化查询方法

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: 数据库查询——索引优化查询方法

数据库查询——索引优化查询方法

本文讲解在数据库查询的时候,一个优化查询的方法,这个方法就是索引优化,讲解其中的原理和实现方法。

简介

首先这是一个简单的数据库,这个数据库很正常,如果采取mybatis-plus进行查询,也就是跟这篇文章中的代码一样:Java图书目录管理系统CRUD展示(springboot+vue+mybatis-plus)

/*
 Navicat MySQL Data Transfer
 Source Server         : localhost_3306
 Source Server Type    : MySQL
 Source Server Version : 80028
 Source Host           : localhost:3306
 Source Schema         : projectdatabase
 Target Server Type    : MySQL
 Target Server Version : 80028
 File Encoding         : 65001
 Date: 31/01/2023 22:24:02
*/
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for book
-- ----------------------------
DROP TABLE IF EXISTS `book`;
CREATE TABLE `book`  (
  `isbn` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `author` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `publisher` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL,
  `pubdate` datetime NOT NULL,
  `price` decimal(10, 2) NOT NULL,
  `id` int NOT NULL AUTO_INCREMENT,
  PRIMARY KEY (`id`, `isbn`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = DYNAMIC;
-- ----------------------------
-- Records of book
-- ----------------------------
INSERT INTO `book` VALUES ('9780439227148', 'The Call of the Wild', 'Jack London', 'Scholastic Press', '2001-01-01 00:00:00', 39.40, 1);
INSERT INTO `book` VALUES ('9787501592401', 'The Old Man and the Sea', 'Ernest Hemingway', 'Knowledge Press', '2023-01-30 00:00:00', 25.80, 2);
INSERT INTO `book` VALUES ('9787501592401', 'The Old Man and the Sea', 'Ernest Hemingway', 'Knowledge Press', '2023-01-31 13:02:42', 25.80, 3);
INSERT INTO `book` VALUES ('9780439227148', 'The Call of the Wild', 'Jack London', 'Scholastic Press', '2023-01-30 16:00:00', 34.90, 6);
INSERT INTO `book` VALUES ('9781772262902', 'Oliver Twist', 'Charles Dickens', 'Engage Books', '2023-01-03 16:00:00', 45.00, 7);
SET FOREIGN_KEY_CHECKS = 1;

索引优化原理

索引优化:使用合适的索引可以加快查询速度。例如,在book表中,isbn、title、author和publisher列都是常用作搜索的字段,应为这些字段建立相应的索引。

索引可以大大提高数据库查询效率,例如在book表中的isbn、title、author和publisher列上建立相应的索引,可以极大地优化图书管理系统的CRUD操作。

以下是为book表中的isbn、title、author和publisher列分别建立索引的SQL语句:

ALTER TABLE `book` ADD INDEX `idx_isbn`(`isbn`);
ALTER TABLE `book` ADD INDEX `idx_title`(`title`);
ALTER TABLE `book` ADD INDEX `idx_author`(`author`);
ALTER TABLE `book` ADD INDEX `idx_publisher`(`publisher`);

执行以上SQL语句即可在book表中为指定列建立索引。在查询时,MySQL会首先使用索引来检索符合条件的记录,并返回结果,从而避免全表扫描,提高查询速度。

需要注意的一点是,在建立索引的同时也会增加数据的维护成本和存储空间。因此,在选择索引字段和类型时应该视情况而定,避免过度使用,以免影响系统性能和空间占用。此外,对于频繁更新的表,过多使用索引也会降低更新速度,并且还会产生锁等额外的开销,需要结合实际需求进行选型配置。

添加索引之后,对于这个book类就是这个样子了

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("book")
public class Book {
    @TableId(type = IdType.AUTO)
    private Long id;
    @TableIndex(name = "idx_isbn", type = IndexType.BTREE)
    private String isbn;
    @TableIndex(name = "idx_title", type = IndexType.BTREE)
    private String title;
    @TableIndex(name = "idx_author", type = IndexType.BTREE)
    private String author;
    @TableIndex(name = "idx_publisher", type = IndexType.BTREE)
    private String publisher;
    private Date pubdate;
    private Double price;
}

最后来一个总结:

简单地说,索引就是数据库中用于提高查询效率的一种数据结构。它可以类比于字典的目录,可以帮助我们更快地定位到需要查询的记录。在数据库中,索引一般用B-tree(平衡树)或哈希表实现。其中,B-tree是一种多阶段平衡树,通常用于处理基于磁盘存储的数据检索;哈希表则主要针对内存型数据库,它可以使读取操作达到O(1)的时间复杂度。

在Mybatis-Plus中,通过@TableIndex注解可以为实体类中的列建立相应的索引,如上述Book实体类中的四个字段isbn、title、author和publisher,分别添加了名为idx_isbn、idx_title、idx_author和idx_publisher的BTREE类型索引。

当进行查询操作时,如果查询语句中带有这些具有索引的字段,则MySQL会选择使用相关的索引来定位符合条件的记录。由于索引能够极大地加快查询操作,因此在实际开发中,我们往往需要为需要经常进行查询的字段添加相应的索引,从而提高系统的响应速度。

需要注意的是,在建立索引的过程中,需要根据实际业务需求选择建立哪些字段的索引,同时需要权衡索引会带来的维护和存储开销。过多或不必要的索引反而会拖慢系统查询和写入速度,因此需要谨慎地进行优化。同时,在数据库数据量较大时,也可以采取分区等方式进行优化以提高性能和可用性。

总之,索引是一种重要的数据库优化手段,可以帮助我们更快地查找和定位需要的数据,但也需要根据实际情况进行优化和管理。

实际案例

假设我们有一个业务需求:需要根据作者名查询图书信息。在默认情况下,我们可以通过以下SQL语句进行查询:

SELECT * FROM book WHERE author = '张三';

但如果book表中数据量非常大,则这样的查询操作可能会耗费很长时间。为了优化查询效率,我们可以针对author字段建立索引,使其能够更快地查询到匹配的记录。

在Mybatis-Plus中,我们可以在Book实体类中对author属性添加@TableIndex注解,代码如下:

@Data
@AllArgsConstructor
@NoArgsConstructor
@TableName("book")
public class Book {
    @TableId(type = IdType.AUTO)
    private Long id;
    private String isbn;
    private String title;
    @TableIndex(name = "idx_author", type = IndexType.BTREE)
    private String author;
    private String publisher;
    private Date pubdate;
    private Double price;
}

然后,在数据库中执行以下SQL语句,为author字段建立相应的BTREE类型的索引:

CREATE INDEX idx_author ON book(author);

这样,当我们通过以下SQL语句查询图书信息时,MySQL数据库就可以使用idx_author索引来提高查询效率:

SELECT * FROM book WHERE author = '张三';

由于索引可以帮助我们更快定位到符合条件的记录,因此当book表中数据量较大时,使用索引会大幅提高查询效率,同时也减轻了数据库的压力。

当然,在实际开发中,我们还需要根据具体业务需求进行优化。例如,如果对多个字段需要进行联合查询,则可以为这些字段创建复合索引等等。

  • 原理分析

加入索引对查询效率的提升主要来自于索引的数据结构和位置,它可以有效地减少数据库中需要扫描的数据量。

在MySQL中,每一个索引都是一棵B-tree或者Hash表。当我们为author字段建立了索引之后,MySQL会把Autor字段的值按照索引的数据结构进行存储,在读取时只需要查找到符合条件的记录即可,而不必遍历整张表。

假设book表有1000万条记录,如果没有为author字段建立索引,则MySQL需要遍历整张表来寻找符合条件的记录,这个操作是非常耗时的。而当我们为author字段建立索引时,MySQL只需要在这棵B-tree上进行检索即可,由于它使用的是平衡树的数据结构,所以它每次最多需要比较log(N)次,其中N是这个B-tree的叶子节点数量。因此使用索引查询的速度是非常快的,甚至可以达到近似O(1)的时间复杂度。

需要注意的是,在实际应用中为表的字段添加索引并不是越多越好,过多的索引也可能会拖慢数据库的写入操作,并消耗大量的磁盘空间。因此,我们需要在对具体的业务需求进行分析和优化之后决定是否需要添加索引,以及需要为哪些字段添加索引。

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
相关文章
|
11天前
|
SQL Oracle 数据库
使用访问指导(SQL Access Advisor)优化数据库业务负载
本文介绍了Oracle的SQL访问指导(SQL Access Advisor)的应用场景及其使用方法。访问指导通过分析给定的工作负载,提供索引、物化视图和分区等方面的优化建议,帮助DBA提升数据库性能。具体步骤包括创建访问指导任务、创建工作负载、连接工作负载至访问指导、设置任务参数、运行访问指导、查看和应用优化建议。访问指导不仅针对单条SQL语句,还能综合考虑多条SQL语句的优化效果,为DBA提供全面的决策支持。
39 11
|
26天前
|
存储 缓存 网络协议
数据库执行查询请求的过程?
客户端发起TCP连接请求,服务端通过连接器验证主机信息、用户名及密码,验证通过后创建专用进程处理交互。服务端进程缓存以减少创建和销毁线程的开销。后续步骤包括缓存查询(8.0版后移除)、语法解析、查询优化及存储引擎调用,最终返回查询结果。
29 6
|
26天前
|
存储 缓存 数据库
数据库索引采用B+树不采用B树的原因?
B+树优化了数据存储和查询效率,数据仅存于叶子节点,便于区间查询和遍历,磁盘读写成本低,查询效率稳定,特别适合数据库索引及范围查询。
37 6
|
1月前
|
SQL 存储 BI
gbase 8a 数据库 SQL合并类优化——不同数据统计周期合并为一条SQL语句
gbase 8a 数据库 SQL合并类优化——不同数据统计周期合并为一条SQL语句
|
1月前
|
SQL 数据库
gbase 8a 数据库 SQL优化案例-关联顺序优化
gbase 8a 数据库 SQL优化案例-关联顺序优化
|
24天前
|
SQL JavaScript 程序员
数据库LIKE查询屡试不爽?揭秘大多数人都忽视的秘密操作符!
本文分析了因数据库中的不可见空白字符导致的数据查询问题,探讨了问题的成因与特性,并提出了使用 SQL 语句修复问题的有效方案。同时,总结了避免类似问题的经验和注意事项。
30 0
|
1月前
|
JSON JavaScript 关系型数据库
node.js连接GBase 8a 数据库 并进行查询代码示例
node.js连接GBase 8a 数据库 并进行查询代码示例
|
7天前
|
存储 Oracle 关系型数据库
数据库传奇:MySQL创世之父的两千金My、Maria
《数据库传奇:MySQL创世之父的两千金My、Maria》介绍了MySQL的发展历程及其分支MariaDB。MySQL由Michael Widenius等人于1994年创建,现归Oracle所有,广泛应用于阿里巴巴、腾讯等企业。2009年,Widenius因担心Oracle收购影响MySQL的开源性,创建了MariaDB,提供额外功能和改进。维基百科、Google等已逐步替换为MariaDB,以确保更好的性能和社区支持。掌握MariaDB作为备用方案,对未来发展至关重要。
27 3
|
7天前
|
安全 关系型数据库 MySQL
MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!
《MySQL崩溃保险箱:探秘Redo/Undo日志确保数据库安全无忧!》介绍了MySQL中的三种关键日志:二进制日志(Binary Log)、重做日志(Redo Log)和撤销日志(Undo Log)。这些日志确保了数据库的ACID特性,即原子性、一致性、隔离性和持久性。Redo Log记录数据页的物理修改,保证事务持久性;Undo Log记录事务的逆操作,支持回滚和多版本并发控制(MVCC)。文章还详细对比了InnoDB和MyISAM存储引擎在事务支持、锁定机制、并发性等方面的差异,强调了InnoDB在高并发和事务处理中的优势。通过这些机制,MySQL能够在事务执行、崩溃和恢复过程中保持
31 3
|
7天前
|
SQL 关系型数据库 MySQL
数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog
《数据库灾难应对:MySQL误删除数据的救赎之道,技巧get起来!之binlog》介绍了如何利用MySQL的二进制日志(Binlog)恢复误删除的数据。主要内容包括: 1. **启用二进制日志**:在`my.cnf`中配置`log-bin`并重启MySQL服务。 2. **查看二进制日志文件**:使用`SHOW VARIABLES LIKE 'log_%';`和`SHOW MASTER STATUS;`命令获取当前日志文件及位置。 3. **创建数据备份**:确保在恢复前已有备份,以防意外。 4. **导出二进制日志为SQL语句**:使用`mysqlbinlog`
36 2