抱歉,您的浏览器无法访问本站
本页面需要浏览器支持(启用)JavaScript
了解详情 >

使用 MySQL 平时编写 SQL 的时候,可以使用 Explain 关键字,根据执行结果进行优化 SQL

如下图通过 Explain 查看 SQL 执行结果

没有索引

根据EXPLAIN结果,我们可以看到以下信息:

  • id: 查询的标识符,这里是1,对于简单的单表查询,通常只有一个。
  • select_type: 查询类型,这里是SIMPLE,表明这是一个不包含子查询或UNION的简单查询。
  • table: 涉及的表名,即user_login_log
  • partitions: 表的分区信息,这里为NULL,意味着表没有使用分区。
  • type: 访问类型,这里是ALL,表示进行了全表扫描,这是效率较低的一种访问方式,意味着没有使用到索引。
  • possible_keys: 可能用到的索引,这里是NULL,表示没有合适的索引可供优化器选择。
  • key: 实际使用的索引,同样为NULL,确认了没有使用索引。
  • key_len: 使用的索引长度,因为没有使用索引,所以也是NULL
  • ref: 与索引比较的列或常量,由于未使用索引,此列为NULL
  • rows: 预计扫描的行数,这里是293706行,表明MySQL预计需要扫描整个表来完成这个查询。
  • filtered: 表示存储引擎返回的数据在server层过滤后,能用到的比例,这里是100%,意味着所有扫描的行都会返回给客户端(在LIMIT限制之前)。
  • Extra: 额外的信息,显示为Using filesort,意味着MySQL需要对结果进行排序,因为没有索引可以直接提供有序的数据,这对于大表和频繁执行的排序查询来说,性能开销较大。

综上所述,当前这个查询没有利用到任何索引,执行时进行了全表扫描并进行了文件排序来完成ORDER BY操作。为了优化这个查询,考虑在login_date字段上创建一个索引,如果经常需要这样的查询并且数据量大,创建一个包含login_datelogin_ip的复合索引可能会更有效,这样不仅可以加速排序,还能覆盖查询避免访问表数据。

一个索引

两个索引

根据您的EXPLAIN输出信息,情况有了变化:

  • id: 依然是1,代表这是一个简单的查询。
  • select_type: 依然是SIMPLE
  • table: 依然是user_login_log表。
  • type: 现在是index,这意味着查询使用了索引进行扫描,但不是通过索引来直接定位记录(这与ALL不同,也不同于通过索引直接找到记录的consteq_ref)。
  • possible_keys: 显示可能使用的索引是idx_user_id,但实际上使用了另一个索引。
  • key: 实际使用的索引是idx_login_date,这与您的问题描述不符,看起来可能是输入时的笔误或是理解上的误会,因为通常EXPLAIN结果中的key列应直接对应于实际采用的索引名。
  • key_len: 4字节,这通常对应于索引字段的大小,对于日期时间类型(如DATETIME或TIMESTAMP),这符合预期。
  • rows: 预计扫描的行数是13行,相比之前的全表扫描大大减少,说明索引正在起作用缩小扫描范围。
  • filtered: 7.16%,表明在索引扫描过程中,预计有7.16%的行是需要的,这个值反映了通过索引筛选后的数据相关性。
  • Extra: Using where,表明虽然使用了索引进行扫描,但是在索引中无法直接找到满足条件的所有列,所以需要回表或者是在已经通过索引筛选出的行中进一步应用WHERE条件过滤。

基于以上信息,看起来查询优化器选择了idx_login_date索引来帮助执行查询,而不是之前讨论的针对特定login_ip的选择。如果您的实际意图是查看关于如何优化原始SQL(即按login_date排序并限制结果数量的查询)的索引使用情况,之前的建议仍然适用:确保login_date上有索引,并考虑是否需要创建一个包含login_datelogin_ip的复合索引来进一步优化排序和查询速度。

评论