记一次因线上mysql优化器误判引起慢查询事件

yizhihongxing

下面我会详细讲解“记一次因线上MySQL优化器误判引起慢查询事件”的完整攻略。

背景

在进行线上MySQL性能优化的过程中,经常会遇到一些奇怪的问题,比如出现奇怪的慢查询,尤其是当使用了ORM框架之后,更容易出现这些问题。在本次攻略中,我们将讨论一次因线上MySQL优化器误判引起的慢查询事件。

问题描述

某天,我们的应用开始出现了一些慢查询,比如说从一个表中查询10条记录,需要10秒钟,而在同样的环境下,同样的查询只需要1秒钟左右,因此我们需要找到这个问题的根本原因,解决掉这个问题。

解决过程

  1. 首先,我们需要排除环境问题,比如说网络或者硬件问题,因此我们抓取了一些慢查询的日志,并进行了分析,发现这些日志中的查询都是从一个特定的表中查询数据,并且这个表只有一些简单的字段。

  2. 我们进一步分析了这个表的结构、索引情况等信息,发现这个表有一个联合索引,可以用于支持我们的查询,因此我们决定尝试使用这个联合索引来查询数据。但是,在使用这个联合索引之后,我们发现查询时间并没有得到改善,速度还是很慢。

  3. 接着,我们进一步分析了问题所在,发现这个问题是由于MySQL优化器误判引起的。我们的联合索引中的字段顺序是有问题的,导致优化器认为这个索引不能用于这个查询,并且使用了一个更差的索引来进行查询,从而导致了性能问题。

  4. 我们经过一些试验,调整了联合索引中的字段顺序,使得优化器可以正确地使用这个索引进行查询,性能问题得到了改善,并且查询时间由10秒钟降低到1秒钟以内。

示例:

示例1

我们有一个表user,包含以下字段:

CREATE TABLE `user` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL,
  `age` int(11) DEFAULT NULL,
  `sex` tinyint(4) DEFAULT '0',
  `email` varchar(50) DEFAULT NULL,
  `phone` varchar(15) DEFAULT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_name` (`name`),
  KEY `idx_age` (`age`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

我们需要查询一个年龄在25-30岁之间的名字为“Tom”的用户,我们可以使用以下语句进行查询:

SELECT * FROM `user` WHERE `age` >= 25 AND `age` <= 30 AND `name` = 'Tom';

但是,这个查询速度非常慢,需要10秒钟才能返回结果。我们可以查看一下这个查询的执行计划:

EXPLAIN SELECT * FROM `user` WHERE `age` >= 25 AND `age` <= 30 AND `name` = 'Tom';

得到的输出结果如下:

+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | user  | NULL       | ALL  | idx_name      | NULL | NULL    | NULL | 1124 |     1.25 | Using where |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------------+

我们发现MySQL选择了一个不太合适的索引进行查询,通过一些调整,我们可以正确地让MySQL选择更好的索引,提升查询速度。

示例2

我们有一个表order,包含以下字段:

CREATE TABLE `order` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `user_id` int(11) NOT NULL,
  `product_id` int(11) NOT NULL,
  `price` decimal(10,2) NOT NULL,
  `status` tinyint(4) NOT NULL DEFAULT '1',
  `created_at` datetime NOT NULL,
  PRIMARY KEY (`id`),
  KEY `idx_user_id` (`user_id`),
  KEY `idx_product_id` (`product_id`),
  KEY `idx_created_at` (`created_at`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8;

我们需要查询一个用户在过去一个月内购买了某个产品,并且这个订单的状态为成功的记录,我们可以使用以下语句进行查询:

SELECT * FROM `order` WHERE `user_id` = 1000 AND `status` = 2 AND `product_id` = 100 AND `created_at` >= DATE_SUB(NOW(), INTERVAL 30 DAY);

但是,这个查询速度非常慢,需要10秒钟才能返回结果。我们可以查看一下这个查询的执行计划:

EXPLAIN SELECT * FROM `order` WHERE `user_id` = 1000 AND `status` = 2 AND `product_id` = 100 AND `created_at` >= DATE_SUB(NOW(), INTERVAL 30 DAY);

得到的输出结果如下:

+----+-------------+-------+------------+------+---------------------+------+---------+------+------+----------+-------------+
| id | select_type | table | partitions | type | possible_keys       | key  | key_len | ref  | rows | filtered | Extra       |
+----+-------------+-------+------------+------+---------------------+------+---------+------+------+----------+-------------+
|  1 | SIMPLE      | order | NULL       | ref  | idx_user_id,idx_idx | idx_user_id | 4     | const |  180 |    20.97 | Using index |
+----+-------------+-------+------------+------+---------------------+------+---------+------+------+----------+-------------+

我们发现MySQL选择了一个不太合适的索引进行查询,通过一些调整,我们可以正确地让MySQL选择更好的索引,提升查询速度。

总结

在这个攻略中,我们讨论了一次因线上MySQL优化器误判引起的慢查询事件。通过分析问题,我们发现出现问题的根本原因是MySQL优化器认为我们使用的索引不适用,选择了一个更差的索引进行查询。通过调整索引中的字段顺序,我们成功地解决了这个问题,提升了查询速度。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:记一次因线上mysql优化器误判引起慢查询事件 - Python技术站

(0)
上一篇 2023年5月19日
下一篇 2023年5月19日

相关文章

  • mysql插入索引太慢 加参数delay_key_write

    插入大数据时,有索引会很慢,可以DISABLE KEYS,或者直接在table中加入DELAY_KEY_WRITE 注: delay_key_write这个参数只对myisam类型表有效 如果你某个表需要经常update操作,这个参数就很管用! 但等delay_key_write使用时,出现断电或重启时,会导致在cache的索引update没来得及更新,所以…

    MySQL 2023年4月13日
    00
  • MySQL优化方案参考

    MySQL优化方案参考攻略 1. 索引优化 1.1 索引分类 MySQL的索引分为主键索引和非主键索引。主键索引是基于表的主键定义的索引,非主键索引则是除主键外的普通索引。 1.2 索引设计原则 建立索引的字段应该尽量选择区分度高的字段,避免对字段的重复值建立索引。否则,索引失效的可能性比较大,建立的索引占用的磁盘空间也较大。 索引字段应该尽量选择长度小于等…

    MySQL 2023年5月19日
    00
  • MySQL性能分析及explain的使用说明

    MySQL性能分析及explain的使用说明 一、MySQL性能分析 MySQL性能分析是通过对MySQL的SQL语句进行优化的一个过程。性能优化的目的是尽可能地缩短相应时间,并且通过优化,提高应用程序的可扩展性。下面是MySQL性能分析的一个简单流程: 确定任何性能问题 分析性能问题 性能问题的解决方案 监控并持续改进 1. 确定任何性能问题 MySQL中…

    MySQL 2023年5月19日
    00
  • MySQL 数据库(一):创建数据库、创建表

    创建数据库 语法:(译:亏诶特。得特贝斯) create database 示例:创建数据库 test; create database test; 创建表 语法:(译:亏诶特。tei bou) create table 表名 (字段1 类型1,字段2 类型2,字段3 类型3) DEFAULT CHARSET=utf8; 解释: 字段名:用来标识表的一列 字…

    MySQL 2023年4月13日
    00
  • MySQL转义字符的使用方法

    MySQL转义字符是一些特殊字符,用于告诉MySQL将其视为普通字符,而不是语句的一部分。常见的转义字符包括反斜杠“\”、“单引号” ‘ ’、“双引号” " "、“换行符” \n、“制表符” \t等。以下是MySQL转义字符的使用方法及实例说明。 使用反斜杠转义特殊字符 反斜杠是MySQL中最常用的转义字符。它可以转义各种特殊字符,如单引…

    MySQL 2023年3月9日
    00
  • MySQL执行SQL语句的流程详解

    MySQL 执行 SQL 语句的流程详解 MySQL 是一种开源的,常见的关系型数据库管理系统。SQL (Structured Query Language)是一种用于管理关系型数据库的语言。在进行数据库操作时,我们需要编写 SQL 语句,MySQL 会根据 SQL 语句的执行计划实现数据的存储和管理。 MySQL 执行 SQL 语句的步骤 1. 连接数据库…

    MySQL 2023年5月19日
    00
  • mysql分页原理和高效率的mysql分页查询语句

    下面我将详细讲解“mysql分页原理和高效率的mysql分页查询语句”的完整攻略。 分页原理 分页是我们在开发Web应用时经常使用的功能,其主要作用是将一大批数据分割成多个小块以便显示在前端。数据库中的分页也是同样的原理,即将一张表中的数据进行分块显示。 在MySQL中,分页最常用的是基于LIMIT关键字实现的分页机制。LIMIT语句可以通过两个参数来进行数…

    MySQL 2023年5月19日
    00
  • mysql server 5.5连接不上的解决方法

    针对“mysql server 5.5连接不上”的问题,我们可以通过以下步骤来解决: 1.检查MySQL服务是否正常启动 在出现连接问题之前,我们需要先确认MySQL服务是否正常启动。可以通过以下步骤来检查: 在Windows系统中,我们可以通过“服务管理器”来检查服务是否启动。具体步骤如下: 通过快捷键Win+R打开运行窗口,输入services.msc,…

    MySQL 2023年5月18日
    00
合作推广
合作推广
分享本页
返回顶部