只要心中有 B-树,SQL 优化就不怵

文章目录

            为什么存在性能问题?
            为什么是 B-树索引?
            优化查询条件
                等值查找
                复合条件
                范围查找
                LIKE 运算符
                使用函数
                空值查找
            多表连接查询
            排序和分组
            DML
            总结

SQL 语句优化是数据库优化的重要内容;无论开发人员还是 DBA,在工作中都不可避免需要解决一些 SQL 性能问题。

SQL 优化的方法有多种,其中最有效、最常用的方法就是索引(Indexing)。因此,我们就来详细讨论一下索引(B-树)的原理,以及如何利用索引编写高性能的 SQL 语句。

本文内容适用于各种数据库,包括但不限于 MySQL、Oracle、SQL Server 、PostgreSQL 以及 SQLite。
为什么存在性能问题?

由于 SQL 是一种关注结果(what)的语言,具体过程(how)由数据库系统来实现,这就往往导致我们容易编写出低性能的 SQL 语句。我们先来看看数据库为什么存在性能问题。

目前,数据库管理系统主要还是使用磁盘作为数据的存储介质;因为磁盘的访问性能虽然比内存慢几个数量级,但是具有价格便宜、大容量和断电不丢失的特性。对于交易类型的数据库(OLTP),一般都是小型的事务,操作很少的随机数据,但是并发很高。这种 IO 密集型数据库操作使用磁盘存储数据文件时存在两个问题:

    直接查找数据时,每次都需要扫描表中的全部数据;
    随着数据量的增长,扫描磁盘数据的性能急剧下降。

下面是一个简单的查询语句,查找 emp_id 等于 5 的员工(数据来源):

select *
from employee
where emp_name = '张三';

那么数据库如何找到我们需要的数据呢?如果没有索引,那就只能扫描整个 employee 表,然后依次判断 emp_name 字段是否等于“张三”并返回满足条件的数据。这种方式一个最大的问题就是当数据量逐渐增加时,全表扫描的性能也就随之明显下降。

因此,数据库的性能优化首先就是需要减少磁盘的访问;其中主要的方法就是利用索引技术。

    📝另一个减少磁盘 IO 的常用方法就是利用内存进行数据缓存,在数据库中称为缓冲区(Buffer Pool、Buffer Cache)。

那么为什么索引能够提高查询的性能?为什么几乎所有的数据库默认使用 B-树索引(B+树、B*树)?这就需要先来了解一下 B-树。
为什么是 B-树索引?

为了解决查询的性能问题,数据库引入了一个新的数据结构:索引。索引就像书籍后面的关键字索引,按照关键字进行排序,并且提供了指向具体内容的页码。如果我们在 id 字段上创建了索引(例如 B-树索引),数据库查找的过程大概如下图所示:
 

B-树(平衡树、Balanced Tree)索引就像是一棵倒立的树,其中的节点按照顺序进行组织;节点左侧的数据都小于该节点的值,节点右侧的数据都大于节点的值。

数据库查找时,首先通过索引找到工号为 5 的节点,再通过该节点上的指针(通常是数据的物理地址)访问数据所在的磁盘位置。举例来说,假设每个索引分支节点可以存储 100 个记录,100 万(1003)条记录只需要 3 层 B-树即可完成索引。通过索引查找数据时需要读取 3 次索引数据(每次磁盘 IO 读取整个分支节点),加上 1 次磁盘 IO 读取数据即可得到查询结果。

相反,如果采用全表扫描,需要执行的磁盘 IO 可能高出几个数量级。当数据量增加到 1 亿时,B-树索引只需要再增加 1 次索引 IO 即可;而全表扫描则需要再增加几个数量级的 IO。

    📝全表扫描并不一定比索引查找更慢,当表中的记录较少,或者查询需要返回表中大部分的数据时,直接通过全表扫描可能更快。

不仅如此,数据库在实现上还对 B-树索引进行了改进,在索引节点之间增加互相连接的指针(B+树、B*树),能够提供更好的范围查询性能。例如,以下是 Oracle 中的 B*树索引示意图:
 

更多请见:http://www.mark-to-win.com/tutorial/51574.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值