怎么解决数据库效率不高的问题

94 阅读4分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第4天,点击查看活动详情

在进行数据库实验的时候,你是否遇到过这样的问题。

为什么我查询一个数据,花了很长时间。

为什么这两个代码看起来差不多第一个更慢,第二个更块?

为什么一个事务里面,我找不到最慢的那条代码?

如果你有以上问题,那么,恭喜你,这篇文章。将会给你提供一种解决思路。

第一个:如果一条查询语句,查询大量数据中某一个,效率太低的问题

解决方案:添加索引

在建表的时候创建索引, 这里举例创建一张 teacher 表,该表有 id、name、age 三个字段,给字段 id 创建索引。

```
DELIMITER ;
CREATE TABLE teacher(
.....
INDEX ix_id(id)    # 给 id 创建的索引名为 ix_id
);
```

给已经存在的表中某字段添加索引

``` CREATE INDEX ix_name ON teacher(name);  ```

修改表时创建索引

```
ALTER TABLE teacher ADD INDEX ix_age(age);
```

当然,一般我们遇到,都是给已经存在的表添加索引,毕竟一开始,我们也不知道索引居然能有这么大作用。

那么为什么索引能提高效率?

其原理是,没有索引时会发生全表扫面,有索引时,会在表外单独为索引数据建立 B+ 树之类的数据结构;根据 id 查询时,会先在树上进行高效查询,获取对应数据行的地址进而提取数据行中的列。

那么有数据结构基础的小伙伴应该了解b+树吧,具体是这样的

image.png

我们可以看到,上一层的数据,存储的刚好是下一层分界点的数据。

比如我查询44

从第一层看,我比33大,比七七小,那么我的位置应该是第二个大格子,就是33开头的那个,那么从22开始,找到对应区间,然后再查。 依次还可以往下演推。

但是索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,因为 insert 或 update 时有可能会重建索引,所以怎样建索引需要慎重考虑,视具体情况而定。一个表的索引数最好不要超过6个,若太多则应考虑一些不常使用到的列上建的索引是否有必要,特别是占内存。

如果查询不能解决,那么我们就需要从sql语句本身下手了

第二个:查询同一个东西,不同的查询方式,有速度差异

比如 已知国家名 Netherlands ,数据库city,country 查询该国所有城市信息:

SELECT * FROM city c1
WHERE EXISTS
(SELECT * FROM country c2 WHERE c1.CountryCode = c2.Code AND c2.Name = 'Netherlands');

我们先在外层查询取得第一行记录,用该记录的相关的属性值(在内层 WHERE 子句中给定的)处理内层查询,若外层的 WHERE 子句返回 True 值,则这条记录放入结果表中。然后再取下一行记录,重复上述过程直到外层表的记录全部遍历一次为止。

那么使用了exists 是不是感jio有点很疑惑。

显然,该语句可改写为:

SELECT * FROM city c1
WHERE c1.countrycode =
(SELECT code FROM country WHERE name = 'Netherlands');

先查询到名字是Netherlands对应的国家,然后再查询这个国家的城市。 在查询结果少的情况下,我们使用第二条合理,查询结果多的花,可用 EXISTS,子查询结果小可用 = 或 IN 等子查询。

第三个,怎么定位到最慢的sql

找到待优化的 SQL 语句需要借助慢查询日志。慢查询日志用于记录执行时间超过设定时间的 SQL 语句,MySQL 默认关闭该日志。查看慢查询日志参数的语句如下:

SHOW VARIABLES LIKE '%query%';

主要关注以下参数:

  • slow_query_log:慢查询日志开启状态;
  • long_query_time:设置一个单位为秒的时间数值,查询时间超出这个值的 SQL 查询被界定为慢查询;
  • slow_query_log_file:慢查询日志的存放路径。

使用 EXPLAIN 关键字分析 SQL 执行效率:

EXPLAIN SELECT * FROM employee WHERE name LIKE '%aaaa%';

好了,以上就是我的一些理解,如果有不对的欢迎指出,也希望他可以帮到大家。