记一条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 ...
随机推荐
- curl发送多维数组
//通过curl模拟post的请求: function SendDataByCurl($url,$data=array()){ //对空格进行转义 $url = str_replace(' ','+' ...
- 算法笔记刷题3(codeup 5901)
今天刷题的速度依旧很慢(小乌龟挥爪.jpg) 我觉得codeup5901中回文串的处理很妙,如果是我自己写的话可能会把数组直接倒过来和原来对比.按照对称规律进行比对的话,工作量可以减少一半. #inc ...
- c++库 c语言接口
//code in add.cxx #include "add.h" int sample::method() { cout<<"method is call ...
- c++中set 的用法
1.关于set C++ STL 之所以得到广泛的赞誉,也被很多人使用,不只是提供了像vector, string, list等方便的容器,更重要的是STL封装了许多复杂的数据结构算法和大量常用数据结构 ...
- 基于口令的密码(PBE)
基于口令的密码(PBE) 基于口令的密码(Password Based Encryption,PBE)是一种基于口令生成密钥,并使用该密钥进行加密的方法.其中加密和解密使用的是同一个密钥. 根据用户自 ...
- http协议请求流程分析
http协议请求流程分析 用户输入URL(地址链接)(http://www.baidu.com:80/tools.html)客户端获取到端口及主机名后,客户端利用DNS解析域名,首先客户端的浏览器会先 ...
- IDEA 之 常用快捷键
1. 编辑 No. 快捷键 功能描述 01 Ctrl+Space 补全代码 02 Ctrl+Shift+Space 补全代码,添加分号结束符 03 Ctrl+q 展示某个类或方法的API说明文档 04 ...
- Vue页面权限控制和动态添加路由
原文转自:点我 页面权限控制 页面权限控制是什么意思呢? 就是一个网站有不同的角色,比如管理员和普通用户,要求不同的角色能访问的页面是不一样的.如果一个页面,有角色越权访问,这时就得做出限制了. Vu ...
- libevent(九)bufferevent
bufferevent,带buffer的event struct bufferevent { struct event_base *ev_base; const struct bufferevent_ ...
- 06_CSS入门和高级技巧(4)
复习 CSS : 负责样式层,层叠式样式表cascading style sheet.CSS2.1,最新版本CSS3. CSS选择器: 选择哪些元素加样式.基本选择3种:标签p.id选择器#id.cl ...