记一条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 >const
GROUP 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 ...
随机推荐
- 一篇文章掌握网页解析神器——xpath
学爬虫不会xpath解析数据? 今天老师带你一堂课带你从零开始精通xpath,从此轻松提取网页信息. 我们在爬虫的过程中,经常会遇到html字符串数据,很多我们需要的数据不是作为标签的文本就是作标签的 ...
- 【<meta name="" content=">】的作用
一.语法: <meta name="name" content="string"/> 二.参数解析: 1.name项:常用的选项有keywords( ...
- java学习(第二篇)语法学习
1.java标识符 类名.变量名以及方法名都被称为标识符. 关于 Java 标识符,有以下几点需要注意: 所有的标识符都应该以字母(A-Z 或者 a-z),美元符($).或者下划线(_)开始 首字符之 ...
- mysql 之 清空表中数据
清空表的时候注意外键约束 命令版 查询数据库中所有表名select table_name from information_schema.tables where table_schema='DB_n ...
- history of program atan2(y,x)和pow(x,y)
编年史 1951 – Regional Assembly Language 1952 – Autocode 1954 – IPL (LISP语言的祖先) 1955 – FLOW-MATIC (COBO ...
- 即将进行论文答辩的我发现MyEclipse 2016 激活过期害得我又一次把 MyEclipse 2016 给重新激活注册,详细的图文解说激活过程
背景: 在家美滋滋的上着网课享受着因为疫情带来的平静,没想到随着微信.钉钉铃声响起打破了我半年以来的平静的生活:通知我们过完劳动节要进行答辩,由于我的答辩项目是由 MyEclipse 这个工具编写的我 ...
- 为什么LIKELY和UNLIKELY要用两个叹号
LIKELY和UNLIKELY的一般定义如下: #define LIKELY(x) (__builtin_expect(!!(x),1))#define UNLIKELY(x) (__builtin_ ...
- OSChina 清明节乱弹 ——准备好纸巾了看乱弹
2019独角兽企业重金招聘Python工程师标准>>> Osc乱弹歌单(2017)请戳(这里) [今日歌曲] @亚麻仔 :分享 范忆堂 的歌曲<酡颜 (夏热版)> 同一个 ...
- windows下遍历文件夹
Github地址 函数: HANDLE WINAPI FindFirstFile( _In_ LPCTSTR lpFileName, _Out_ LPWIN32_FIND_DATA lpFindFil ...
- zabbix tigger 设置
设置一个内存在10分钟内持续低于某值才告警: 设置方法: 修改模板的tigger configuration - > Template OS linux Active(选择自己的模板)-&g ...