记一条distinct 语句的优化。
语句是这条
SELECT DISTINCT bank, account FROM sdb_payments WHERE status="succ";
status 上有索引,但不是主索引。
status 字段 `status` enum('succ','failed','cancel','error','progress','invalid','timeout','ready') NOT NULL DEFAULT 'ready'
我本来以为这是 一条很普通的语句,但是平均执行时间达到了接近3s 。数据量是25w ,
接着是explain
1 | SIMPLE | sdb_payments | ref | status | status | 1 | const | 123886 | Using where; Using temporary
using temporary 这个就很让人疑惑了。distinct 居然要用临时文件,在我的理解,using filesort 和using temporary 都是比较慢的操作,因为设计磁盘的io会很多。
接着是profile 详细支出。
set profiling =1;
SELECT distinct bank, account FROM sdb_payments WHERE status="succ";
show profiles;
+----------+------------+----------------------------------------------------------------------+
| Query_ID | Duration | Query |
+----------+------------+----------------------------------------------------------------------+
| 1 | 1.20948900 | SELECT distinct bank, account FROM sdb_payments WHERE status="succ" |
+----------+------------+----------------------------------------------------------------------+
show proflie for query 1;
+--------------------------------+----------+
| Status | Duration |
+--------------------------------+----------+
| starting | 0.000060 |
| checking query cache for query | 0.000071 |
| Opening tables | 0.000021 |
| System lock | 0.000008 |
| Table lock | 0.000034 |
| init | 0.000140 |
| optimizing | 0.000019 |
| statistics | 0.000088 |
| preparing | 0.000030 |
| Creating tmp table | 0.000040 |
| executing | 0.000009 |
| Copying to tmp table | 2.512772 |
| Sending data | 0.000056 |
| end | 0.000007 |
| removing tmp table | 0.000017 |
| end | 0.000008 |
| query end | 0.000007 |
| freeing items | 0.000027 |
| storing result in query cache | 0.000275 |
| logging slow query | 0.000014 |
| logging slow query | 0.000065 |
| cleaning up | 0.000009 |
+--------------------------------+----------+
为啥会有tmp table 呢,看文档。
In most cases, a DISTINCT clause can be considered as a special case of GROUP BY. For example, the following two queries are equivalent:
SELECT DISTINCT c1, c2, c3 FROM t1
WHERE c1 >const; SELECT c1, c2, c3 FROM t1
WHERE c1 >constGROUP BY c1, c2, c3;
大多数情况下,distinct 都会转化为group by 的语句,
所以再看group by的优化:
The most general way to satisfy a GROUP BY clause is to scan the whole table and create a new temporary table where all rows from each group are consecutive, and then use this temporary table to discover groups and apply aggregate functions (if any). In some cases, MySQL is able to do much better than that and to avoid creation of temporary tables by using index access.
通常情况下,group by会扫描整个表,然后创建一个临时表。。 这里不是很明白。在某些情况下,mysql能用所以而避免用临时表。
SELECT distinct bank, account FROM sdb_payments WHERE status="succ" 这句sql 我觉得是被优化器转化为
SELECT bank, account FROM sdb_payments WHERE status="succ" group by bank,account
这里我添加( bank,account)的联合索引,发现还是没有走索引。。
难道是我想错了?
于是再次explain ,这次加上extended ,然后 马上show warnings ,可以看到解析器是怎么解析sql 的。
Note | 1003 | select distinct `test`.`sdb_payments`.`bank` AS `bank`,`test`.`sdb_payments`.`account` AS `account` from `test`.`sdb_payments` where (`test`.`sdb_payments`.`status` = 'succ' )
想了想,应该把status 也加到索引里面去,变成(status,bank,accout),然后发现
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+--------------+------+----------------+---------+---------+-------+--------+----------+--------------------------+
| 1 | SIMPLE | sdb_payments | ref | status,idx_acc | idx_acc | 1 | const | 123917 | 100.00 | Using where; Using index |
速度极快。
记一条distinct 语句的优化。的更多相关文章
- 52 条 SQL 语句性能优化策略,建议收藏
本文会提到 52 条 SQL 语句性能优化策略. 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在where及order by涉及的列上建立索引. 2.应尽量避免在where子句中对字段进行nul ...
- 记一条sql语句优化
傻瓜级的.此sql语句存在于分销王系统中. 查阅slow log ,时间设置1s 发现很多 SELECT r.*, goods_id, bn, name FROM sdb_goods_rate r, ...
- Mysql 52条SQL语句性能优化策略汇总
1.对查询进行优化,应尽量避免全表扫描,首先应考虑在where及order by涉及的列上建立索引. 2.应尽量避免在where子句中对字段进行null值判断,创建表时NULL是默认值,但大多数时候应 ...
- 【夯实Mysql基础】记一次mysql语句的优化过程
1. [事件起因] 今天在做项目的时候,发现提供给客户端的接口时间很慢,达到了2秒多,我第一时间,抓了接口,看了运行的sql,发现就是 2个sql慢,分别占了1秒多. 一个sql是 链接了5个表同时使 ...
- 【夯实Mysql基础】记一次mysql语句的优化过程!
1. [事件起因] 今天在做项目的时候,发现提供给客户端的接口时间很慢,达到了2秒多,我第一时间,抓了接口,看了运行的sql,发现就是 2个sql慢,分别占了1秒多. 一个sql是 链接了5个表同 ...
- MySQL中一条更新语句是如何执行的
1.创建表的语句和更新的语句 这个表的创建语句,这个表有一个主键ID和一个整型字段c: mysql> create table T(ID int primary key, c int); 如果要 ...
- sql执行万条update语句优化
几个月没有更新笔记了,最近遇到一个坑爹的问题,顺道记录一下.. 需求是这样的:一次性修改上万条数据库. 项目是用MVC+linq的. 本来想着用 直接where() 1 var latentCusto ...
- 给你一条sql语句如何进行优化
我们sql语句的书写是根据业务逻辑进行书写的,如果执行比较慢,那么我们对sql重写: 如分步查询,然后在代码层进行拼接:用临时表:改变sql语句的写法等等.我们称之为逻辑层优化. 然后我们看看每条sq ...
- 记一条复杂的PHP中写的关于查询的mysql语句
$sql="select p.*,q.md from xz_laptop as p inner join xz_laptop_pic as q on p.lid=q.lid title li ...
随机推荐
- BATJ高级Java面试题分享:JVM+Redis+Kafka +数据库+设计模式
话不多说,直接上面试题,来看一下你还欠缺多少? Mysql 与 Oracle 相比, Mysql 有什么优势? 简洁描述 Mysql 中 InnoDB 支持的四种事务隔离级别名称,以及逐级之间的区别? ...
- 安卓微信浏览器中window.location.href失效的问题
最近接手一微信项目,测试功能时,发现跳转在android手机上不动了.iso系统可以正常跳转的.解决方法: window.location.href = url + '?v=' + (new Date ...
- memcache---mongodb---redis比较
Memcached的优点: Memcached可以利用多核优势,单实例吞吐量极高,可以达到几十万QPS(取决于key.value的字节大小以及服务器硬件性能,日常环境中QPS高峰大约在4-6w左右). ...
- java学习(第二篇)语法学习
1.java标识符 类名.变量名以及方法名都被称为标识符. 关于 Java 标识符,有以下几点需要注意: 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($).或者下划线(_)开始 首字符之 ...
- Ubuntu 修改 hosts 文件
sudo vi /etc/hosts sudo /etc/init.d/networking restart
- git取消跟踪(unversion)
有时候我们会git add了一些不想跟踪的文件,通过下面的命令可以在没提交前从index里删掉跟踪记录(保留本地文件) git rm –cached 文件名
- VulnHub靶场学习_HA: Chanakya
HA-Chanakya Vulnhub靶场 下载地址:https://www.vulnhub.com/entry/ha-chanakya,395/ 背景: 摧毁王国的策划者又回来了,这次他创造了一个难 ...
- Robot Framework -003 在Windows10 安装Eclipse作为编辑器,安装 RED 插件。
本文采用Eclipse及其对应的插件来编辑.管理.运行Robot Framework. https://www.eclipse.org/downloads/ 本文安装 Eclipse IDE 2 ...
- 关于Pandownload和百度网盘
本周,百度网盘第三方客户端 Pandownload 被查,开发者被“跨省追捕”:百度网盘“用户激励计划”在未充分告知用户的情况下,利用用户自己的电脑做 P2P 上传节点.这两件事再度引发了对百度网盘的 ...
- 【java基础】01 计算机基础知识
一.计算机基础知识 1. 计算机 1. 什么是计算机? 计算机在生活中的应用举例 计算机(Computer)全称:电子计算机,俗称电脑.是一种能够按照程序运行,自动.高速处理海量数据的现代化智能电子设 ...