(转)仅供自己学习,特此转发

普遍遇到的慢SQL有以下三种:

 1.未走索引
 2.where条件里包含子查询,多表联查
 3.查询大量数据

解决

一.索引:SQL中的高速公路

但凡优化SQL,首先要看的就是这条查询是否走了索引。走索引的查询和没走索引的差距可谓云泥之别。

可以看下面这个例子:

在一张大约3W数据量的用户表中,两种查询方式在速度上的差距:

不走索引:

select * from kw_user_copy where new_id=1
时间: 0.321 s

走主键索引:

select * from kw_user_copy where id=1
时间: 0.002 s

执行时间上有着数百倍的差距。

这种差距如果放在一些大的嵌套中,譬如循环查询500次,将成为非常致命的问题,甚至可能让程序执行超时。

PS. 很多查询条件也会导致SQL放弃索引而执行全表遍历,譬如:

select id from item where num is null

这些细节也要引起注意。

实际项目中的例子:

select id as user_id, name, nickname, photo, status, sdk_key, sdk_status from kw_user where name = 'wallkop' AND password = '44209a6a592dea91bcf7d4dd53e47a5a'
时间: 0.247 s

这是一条非常常见的用户登录查询。

直观看起来,这条SQL似乎写的非常完善了,根据name和password去查询相关用户的信息,怎么看都没有优化的余地了。

我们也知道:name和password作为两个string字段,通常是不会建立索引的,也就是说,这是一条必然不走索引的查询。

这种查询就没有优化余地了吗?

非也。

下面就是一个简单的优化:

select id from kw_user where name = 'wallkop' AND password = '44209a6a592dea91bcf7d4dd53e47a5a'
时间: 0.060 s
 
select id as user_id, name, nickname, photo, status, sdk_key, sdk_status from kw_user where id=37215
时间: 0.001 s
 
总耗时:0.061 s

将一条查询语句拆成两条,第一条不走索引的查询,我们尽量去简化它,只查一个id字段,你会惊奇的发现:速度居然提升了4倍。

而第二条查询用户详细信息的SQL,我们走了主键索引,仅仅用了0.001s。

如此一来,两条查询加起来总耗时才0.061s,比之前快了4倍。

这就是索引的灵活运用之道。

二.子查询(多表联查)优化

子查询速度慢的原因非常简单:

主查询遍历多少条数据,就要执行多少遍子查询。

简单来说,一张只有50条数据的表,普通查询和复杂子查询是没什么速度差异的,但当数据量级达到几万甚至几十万的时候,这个差距就会非常明显。

分析一条SQL语句来说明:

select id from kw_question where game_id=2 AND status=2 AND id in (select question_id from kw_answer where question_id = kw_question.id AND answer like "%瑞文%");
时间: 0.063 s

在这个语句中,where末端是一个非常坑爹的模糊文字子查询

但乍一看这条SQL速度似乎也不算太慢,其原因就在于:game_id=2和status=2这两个查询条件大幅度缩小了需要查询的数据集范围。

这就给我们了一个优化思路:

如果我能在执行子查询前,尽可能的缩减它的“数据范围”,不就可以提高查询效率了么?

分析一个实际项目里的案例,根据数据特点突破了SQL速度的极限:

select id as question_id, question, game_id, modify_time, has_attachment, status from kw_question a
where game_id=2 AND status in (0,1,2) AND not exists( select id from kw_answer where question_id=a.id and status != -1) order by a.create_time desc limit 0,20
时间: 3.160 s

上述SQL是一个问题列表页的查询语句,业务要求是把符合where条件的零回答数据筛选出来。

其实对于这种查询,最简单高效的方式是在字段里加一个answer_num,手动记录每个问题下的答案数量。

但是由于相关业务比较复杂,涉及审核、关闭、二次编辑等流程,最终项目组放弃了这个字段的使用。

所依在kw_question表缺乏相关answer_num字段的情况下,查询一个“零回答”的问题,就得去查其相关联的表:kw_answer。

这就由一个简单的单表查询变成了多表联查,大幅度增加了时间性能损耗。

平心而论,单纯从SQL的角度来讲,这条SQL已经没啥能优化的了,在无法使用answer_num这个字段的情况下,它已经写的蛮不错了。

然而3.16秒的速度真的让人无法接受。

于是开始思考:

首先EXPLAIN分析,发现主查询中rows多达157269条,难怪这么慢。

结合“零回答”这个特点仔细想了想,发现某个问题一旦有了至少一个答案,就彻底摆脱了0回答,通常来讲这个过程是不可逆的。

这就导致了这15W次查询中,大部分查询是废查询,因为你知道那些数据根本不会变动,但SQL还是把它们全部遍历了一次。

三.大量数据查询优化

1、首先分析有没有用到索引

2、

PHP的SQL语句优化的更多相关文章

  1. 优化数据库的方法及SQL语句优化的原则

    优化数据库的方法: 1.关键字段建立索引. 2.使用存储过程,它使SQL变得更加灵活和高效. 3.备份数据库和清除垃圾数据. 4.SQL语句语法的优化.(可以用Sybase的SQL Expert,可惜 ...

  2. oracle之sql语句优化

    oracle之sql语句优化 sql语句的优化 1.在where子句中使用 is null 或 is not null 时,oracle优化器就不能使用索引了. 2.对于有连接的列,即使最有一个是静态 ...

  3. 数据库 基于索引的SQL语句优化之降龙十八掌(转)

    一篇挺不错的关于SQL语句优化的文章,因不知原始出处,故未作引用说明! 1 前言      客服业务受到SQL语句的影响非常大,在规模比较大的局点,往往因为一个小的SQL语句不够优化,导致数据库性能急 ...

  4. 数据库的优化(表优化和sql语句优化)

    在这里主要是分为表设计优化和sql语句优化两方面来实现. 首先的是表设计优化: 1.数据行的长度不要超过8020字节.如果是超过这个长度的话这条数据会占用两行,减低查询的效率. 2.能用数字类型就不要 ...

  5. MySQL常用SQL语句优化

    推荐阅读这篇博文,索引说的非常详细到位:http://blog.linezing.com/?p=798#nav-3-2 在数据库日常维护中,最常做的事情就是SQL语句优化,因为这个才是影响性能的最主要 ...

  6. 浅谈mysql配置优化和sql语句优化【转】

    做优化,我在这里引用淘宝系统分析师蒋江伟的一句话:只有勇于承担,才能让人有勇气,有承担自己的错误的勇气.有承担错误的勇气,就有去做事得勇气.无论做什么事,只要是对的,就要去做,勇敢去做.出了错误,承担 ...

  7. sql语句优化总结

    sql语句优化总结 数据库优化的几个原则: 1.尽量避免在列上做运算,这样会导致索引失败: 2.使用join是应该用小结果集驱动大结果集,同时把复杂的join查询拆分成多个query.不然join的越 ...

  8. MySQL基础操作&&常用的SQL技巧&&SQL语句优化

    基础操作     一:MySQL基础操作         1:MySQL表复制             复制表结构 + 复制表数据             create table t3 like t ...

  9. 关于索引的sql语句优化之降龙十八掌

    1 前言       客服业务受到SQL语句的影响非常大,在规模比较大的局点,往往因为一个小的SQL语句不够优化,导致数据库性能急剧下降,小型机idle所剩无几,应用服务器断连.超时,严重影响业务的正 ...

  10. SQL系列 - SQL语句优化个人总结

    关于SQL语句优化方法 有些是通用的(如避免Select *): 有些不同的数据库管理系统有所区别(如Where子句顺序): 然后必须根据实际环境进行调优,因为即使是相同的数据库和表,在数据量或其他环 ...

随机推荐

  1. synchronized与volatile的区别及各自的作用、原理(学习记录)

    synchronized与volatile的区别,它们的作用及原理? 说到两者的区别,先要了解锁提供的两种特性:互斥(mutual exclusion) 和可见性(visibility). 互斥:即一 ...

  2. AdminLTE 前端框架

    适合运维平台  后台管理系统 AdminLTE 是一个开源的后台控制面板和仪表盘 WebApp 模板. 这是一个快速的HTML模板,基于CSS框架的引导. 文档: http://adminlte.la ...

  3. 在delphi中生成GUID

    什么是 GUID ? 全球唯一标识符 (GUID) 是一个字母数字标识符,用于指示产品的唯一性安装.在许多流行软件应用程序(例如 Web 浏览器和媒体播放器)中,都使用 GUID. GUID 的格式为 ...

  4. vue動畫和過渡

    過渡: 插入.更新和溢出DOM時,提供不同的方式應用過渡效果: vue提供內置的封裝組件,用於包裹要實現過渡效果的內容. <transition name="a">&l ...

  5. Learning to Rank for IR的评价指标—MAP,NDCG,MRR

    转自: https://www.cnblogs.com/eyeszjwang/articles/2368087.html MAP(Mean Average Precision):单个主题的平均准确率是 ...

  6. PHPStorm 配置命名空间

    文件-设置-Directories 选中:application     点击顶部:Sources,右侧会出现 Source Floders 配置项 点击:p进行设置 输入app\

  7. undefined reference to `cv::VideoCapture

    出现opencv链接的问题原因: 1. 路径设置不正确,caffe会优先搜索Makefile.config里面的环境设置 2. anaconda2装的opencv和配置的opencv路径不一致 比如, ...

  8. 为AI提供数据:构建2017数据创新的总结

    本周在微软年度大会上,我们正在讨论组织如何依靠开发人员创造突破性的经验.随着大数据,云和人工智能的融合,创新与破坏正在加速,从未见过.数据是这一融合核心的关键战略资产.当结合云的无限计算能力和机器学习 ...

  9. Clear Linux 为脚本语言提供更高的性能

    导读 Clear Linux的领先性能不仅限于C/C++应用程序,而且PHP,R和Python等脚本语言也有很大的提升速度.在一篇新的博客文章中,英特尔的一位开发人员概述了他们对Python的一些性能 ...

  10. No more tricks, Mr Nanguo HDU - 3292(pell + 矩阵快速幂)

    No more tricks, Mr Nanguo Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Jav ...