如何使用MariaDB的慢查询做MySQL优化 联合索引 最左匹配原则

序言数据库慢查询优化是数据库使用中必须掌握的功能,与其让用户因为5s的长延迟而流逝,不如通过慢查询优化那些丑陋的SQL查询

实验版本:MariaDB 10.5

MariaDB开启慢查询条件

慢查询开启,需要通过配置文件,这个配置文件根据你的安装目录不同而不同,但是一般都是在C:\Program Files\MariaDB 10.5下。文件名称是my.ini
如果以上命令都无法查看 MariaDB 的配置文件路径,你可以尝试在 MariaDB 中执行 SHOW VARIABLES; 命令,查看其中是否有 basedir 和 datadir 参数的输出。basedir 参数指定 MariaDB 的安装路径,datadir 参数指定 MariaDB 数据库文件的存储路径,可以通过这些参数的值来推断 MariaDB 的配置文件路径。或者直接使用
SHOW VARIABLES LIKE 'basedir'

my.ini常见配置选项

MySQL/MariaDB的配置文件中有很多不同的选项,这些选项控制了数据库的各种行为。下面是一些常见的选项及其作用:

bind-address:指定数据库服务器监听的IP地址,可以是单个IP地址或IP地址的列表。
port:指定数据库服务器监听的端口号。
datadir:指定数据库文件存储的路径。
log_error:指定错误日志的路径。
slow_query_log_file:指定慢查询日志的路径。
max_connections:指定数据库服务器支持的最大连接数。
character_set_server:指定数据库服务器使用的默认字符集。
collation-server:指定数据库服务器使用的默认排序规则。
default-storage-engine:指定数据库服务器默认使用的存储引擎。
innodb_buffer_pool_size:指定InnoDB存储引擎使用的缓冲池大小。
query_cache_size:指定查询缓存的大小。
log_queries_not_using_indexes:启用后,记录未使用索引的查询。
这些选项只是MySQL/MariaDB配置文件中的一小部分,具体的选项还会根据不同的版本和使用场景而有所不同。

通过配置文件字段设置启用慢查询

要启用慢查询,需要在配置文件中设置以下参数:

slow_query_log:将该参数设置为1,开启慢查询日志。

slow_query_log_file:指定慢查询日志文件的路径和名称。

long_query_time:指定查询执行时间超过多少秒才被认为是慢查询

slow_query_log=1(MySQL用1)
slow_query_log = ON(mariaDB用ON)
slow_query_log_file = /var/log/mysql/mysql-slow.log
long_query_time=5

这将开启慢查询日志,并将查询执行时间超过5秒的查询记录到/var/log/mysql/mysql-slow.log文件中。

如果你在配置文件中没有指定慢查询日志文件的位置,MySQL会在默认情况下将慢查询日志文件存储在数据目录下,并按照主机名和日志文件类型进行命名,例如:[hostname].log。

在这种情况下,如果你的MySQL数据目录为/var/lib/mysql/,慢查询日志文件将存储在/var/lib/mysql/[hostname].log的位置。不过具体位置还取决于你的系统平台和MySQL版本。

在修改了配置文件后,需要重启数据库才能让配置生效。因此,您需要重启 MariaDB 10.5 以启用慢查询。修改了配置文件后,连接到数据库并不会使更改立即生效。

果您正在Windows操作系统上运行MariaDB 10.5,则可以使用以下方法重启MariaDB:

打开Windows命令提示符(CMD)或Windows PowerShell。

输入以下命令,以停止MariaDB服务:

net stop mariadb

输入以下命令,以启动MariaDB服务

net start mariadb

在 Windows 上启动 MariaDB 10.5,可以通过以下步骤完成:

打开命令提示符或 PowerShell。

使用 cd 命令进入 MariaDB 的 bin 目录,该目录通常位于 MariaDB 安装目录下。

执行以下命令启动 MariaDB 服务:

mysqld.exe --console

如果你在 Windows 上通过 cmd 启动了 MariaDB,关闭 cmd 窗口不会停止 MariaDB 服务的运行。MariaDB 会以服务的形式在后台运行,除非手动停止服务或者重启计算机。

确保使用慢查询成功

SHOW VARIABLES LIKE 'slow_query_log';

如果输出结果中的 Value 为 ON,表示慢查询日志已经开启了;如果为 OFF,则表示慢查询日志未开启。

参数被覆盖了修改的配置文件不是正在使用的配置文件

如果你在 Windows 系统中执行 mysql --help | grep "Default options" 命令遇到了 'grep' 不是内部或外部命令,也不是可运行的程序或批处理文件。 的错误提示,那么说明你的系统上没有安装 grep 命令。

在 Windows 系统中,你可以使用 findstr 命令来替代 grep 命令,例如:

mysql --help | findstr "Default options"

该命令会输出 MariaDB 配置文件的默认搜索路径,你可以根据该路径找到 MariaDB 的配置文件并修改它。

多个 查询、分组、排序、条件时为什么应该使用联合索引

在多个查询条件时,如果使用联合索引,可以减少I/O操作的次数,从而提高查询效率。同时,在分组和排序操作中,联合索引也能够有效地优化查询性能。

举个例子来说,假设我们有一个订单表,包含订单号、商品ID、订单日期、订单状态和订单金额等字段。如果我们经常需要按照订单日期和订单状态进行查询、分组和排序,那么可以创建一个联合索引,包括订单日期和订单状态两个字段。

这样,当我们执行类似于以下SQL查询时:

SELECT 订单日期, 订单状态, SUM(订单金额) 
FROM 订单表 
WHERE 订单日期 BETWEEN '2022-01-01' AND '2022-01-31' 
AND 订单状态 = '已付款' 
GROUP BY 订单日期, 订单状态 
ORDER BY 订单日期 DESC, 订单状态 ASC

数据库可以直接使用联合索引,根据订单日期和订单状态进行索引查找,从而快速定位到符合条件的数据行。这样就可以大大减少I/O操作的次数,提高查询效率,特别是在数据量较大的情况下效果更加明显。

如果没有创建联合索引,数据库需要扫描整张表来查找符合条件的数据行,从而导致查询效率下降。因此,在多个查询、分组、排序条件时,建议使用联合索引来优化查询性能。

如何设置联合索引呢?

设置联合索引需要使用CREATE INDEX语句,并在索引名称后指定需要建立索引的列名。例如,要为表users的name和age列建立联合索引,可以使用以下语句

CREATE INDEX idx_users_name_age ON users (name, age);

将在表users上创建一个名为idx_users_name_age的联合索引,该索引将同时包括name和age列。值得注意的是,联合索引的顺序非常重要,因为它们将按照建立索引时指定的顺序进行排序和搜索。因此,需要根据查询的需求和数据的特点来确定联合索引的列的顺序。

查询需去显式地指定联合索引吗?

查询时无需显式指定联合索引。当查询语句中的条件可以使用联合索引进行匹配时,数据库系统会自动选择使用联合索引。例如,如果一个联合索引包含了字段A和B,并且查询语句中包含了条件"WHERE A=xxx AND B=yyy",那么数据库系统会自动选择使用该联合索引进行查询。

前提是设置了联合索引才行吗?

是的,前提是你设置了联合索引,系统会自动选择最合适的索引。如果没有设置联合索引,系统将根据查询条件进行全表扫描,效率较低。因此,在需要联合查询的列上设置合适的联合索引,可以显著提高查询效率。

最左匹配原则简介

  • 最左匹配原则是指在使用多列索引进行查询时,数据库引擎只能使用索引中最左边的列来优化查询。如果查询中使用的列不是最左边的列,那么该索引就不能被用来优化查询,而是必须扫描整个表。这就是为什么在创建索引时,应该把最常用的列放在最左边。

最左匹配原则工作原理

CREATE TABLE mytable (
    id INT NOT NULL PRIMARY KEY,
    name VARCHAR(50),
    age INT,
    gender VARCHAR(10)
);

CREATE INDEX idx_name_age ON mytable (name, age);

SELECT * FROM mytable WHERE name='John' AND age=25;

在这个示例中,我们创建了一个名为 idx_name_age 的联合索引,该索引包括 name 和 age 两个字段。当我们查询 mytable 表时,使用了 name 和 age 两个条件。由于联合索引是按照多个字段的组合值排序的,所以查询引擎只需要在索引中查找 name='John' 的值,然后再查找该值中 age=25 的数据行,而不是扫描整个表来查找匹配的行,从而提高了查询的效率。

不满足最左匹配原则的情况(顺序错误)

比如只创建了name,age,gender的联合索引,使用如下查询语句:

SELECT * FROM mytable WHERE gender='male' AND age=25;

则MySQL不会使用该联合索引进行查询优化,因为最左前缀规则的原则是,必须按照联合索引中定义的顺序,从左到右匹配查询条件。在这个例子中,虽然gender和age都包含在联合索引中,但查询条件中先出现了gender,而不是age,因此MySQL无法使用该索引进行优化。

不满足最左匹配原则的情况(没有包含联合索引的最左边的列或一组顺序列)

比如你创建了name,age,gender的联合索引,使用如下查询

SELECT * FROM mytable WHERE age=25 and gender='male'

或者

SELECT * FROM mytable WHERE name='jake' and gender='male'

不会利用到该联合索引,因为第一行age和gender,第二行name和gender在联合索引中的位置是不满足最左匹配原则的。因此会导致全表扫描,不可以充分利用联合索引的优势,提高查询效率。

但是注意这个索引的查询效率可能不如创建一个单独的(age,gender)联合索引,因为它不能直接满足(age,gender)的联合查询。

因此,在创建联合索引时,应该根据实际的查询需求来确定索引列的顺序,以使得最常用的列在最左边,这样可以有效地提高查询性能。~~

总结最左匹配原则

最左匹配原则是指我创建了一个联合索引依次包含x,y,z字段。要想借助这个联合索引就必须满足查询中的字段出现顺序为x,y或者x,y,z否则就不能使用,对吗?

是的,您理解得很正确,最左匹配原则是指当一个联合索引包含多个列时,在查询中只使用联合索引的最左边的列或者最左边的一组列,才能利用该联合索引进行查找和排序。如果查询中的列没有遵循索引的顺序,则无法使用联合索引

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注