数据库方面,我会使用MySQL来讲解

为什么需要优化SQL

性能低,执行时间长,SQL语句写的垃圾(特别是嵌套查询),索引失效,服务器参数不合理(缓存,线程数)

SQL优化的重点

SQL优化上面说了几个原因,其中最重要的就是索引的优化,索引就是汉语词典里面的目录,有目录,我可以很容易的找到想查的字,没有目录,只能一页一页的翻查,这样效率就很低了

索引

索引的结构

索引是数据结构,有B树,二叉树,Hash树等等,MySQL用的是B树里的B+树

B树的原理就是:小的放左边,大的放右边

例如下图,索引建立在age字段上,B树结构如右

上图很直观的看出,不加索引,查age=33需要5次,加了索引,查索引,只需要3次。这还是小数据量,假如是百万级别的数据量,那效率会非常高

索引的优缺点总结:

索引的优势:

  1. 提高查询效率(降低IO的使用率)
  2. 降低CPU的使用率(例如order by age desc,没有索引需要排序,有索引,B树本身就已经排好序了)

索引的弊端:

  1. 索引本身很大,存放在内存/硬盘之中(一般存放在硬盘)
  2. 少量数据时不适合使用索引,比如就几个数据,没必要
  3. 频繁更新的字段,不适合使用索引。比如上面的age字段,频繁更新的话索引也要跟着频繁更新,不适合
  4. 很少使用的字段不适合使用索引,比如上面的age字段,我查询的时候几乎不使用这个,那我在这个字段上建立索引干嘛
  5. 索引会提高查询的效率,但是会降低增删改的效率,每次的增删改都要对索引进行更新,不适合

索引的分类

  1. 单值索引:单列加索引,比如age字段加索引
  2. 唯一索引:也是单列加索引,但是这一列不能重复,一般是id列
  3. 复合索引:多个列构成的索引,比如 name+address,先根据名字查人,名字一样的话,再根据地址查人。

索引操作

以我的Message表为例,创建索引的模板如下:

方式一:create 索引类型 索引名 on 表(字段)

#创建单值索引
CREATE INDEX command_index on message(COMMAND) #创建唯一索引
CREATE UNIQUE INDEX id_index on message(ID) #创建复合索引
CREATE INDEX COMMAND_CONTENT_index on message(COMMAND,CONTENT)

方式二:alter table 表名 索引类型 索引名(字段)

#创建单值索引
ALTER TABLE message add INDEX command_index(COMMAND) #创建唯一索引
ALTER TABLE message add UNIQUE INDEX id_index(ID) #创建复合索引
ALTER TABLE message add INDEX COMMAND_CONTENT_index(COMMAND,CONTENT)

这两种创建索引的方式,使用哪个都可以

注意:如果一个字段是primary key,那么默认就是主键索引

主键索引和唯一索引差不多,唯一的区别就是主键索引不能为null

查询索引

show index from 表名

删除索引

drop index 索引名 on 表名

B树

实战

我们先来创建三个表

create table teacherCard(
tcid int,
tcdesc nvarchar(10)
)
create table teacher(
tid int,
tname nvarchar(10),
tcid int
)
create table course(
cid int,
cname nvarchar(10),
tid int
)

里面的数据自己填,这是我的

INSERT INTO test.course (cid, cname, tid) VALUES (1, '编曲', 1);
INSERT INTO test.course (cid, cname, tid) VALUES (2, '编程', 2);
INSERT INTO test.course (cid, cname, tid) VALUES (3, '作曲', 3);
INSERT INTO test.course (cid, cname, tid) VALUES (4, '遛狗', 1);
INSERT INTO test.teacher (tid, tname, tcid) VALUES (1, '许嵩', 1);
INSERT INTO test.teacher (tid, tname, tcid) VALUES (2, '蜀云泉', 2);
INSERT INTO test.teacher (tid, tname, tcid) VALUES (3, '林俊杰', 3);
INSERT INTO test.teachercard (tcid, tcdesc) VALUES (1, '许嵩最佳歌手');
INSERT INTO test.teachercard (tcid, tcdesc) VALUES (2, '蜀云泉只会编程');
INSERT INTO test.teachercard (tcid, tcdesc) VALUES (3, '林俊杰作曲');

问题

查询出课程编号为2或者教师证编号为3的老师的信息?(不要看答案,自己写写试试)

我的答案:

select t.* from course c inner join teachercard tc
on c.tid=tc.tcid and (c.cid=2 or tc.tcid=3) inner join teacher t on t.tcid=tc.tcid

这就是我第一反应的SQL水平.......

我们加一个执行计划explain来,试试结果。explain就是看一条SQL语句的执行计划的

explain select t.* from course c inner join teachercard tc
on c.tid=tc.tcid and (c.cid=2 or tc.tcid=3) inner join teacher t on t.tcid=tc.tcid

结果如下

把上述的SQL语句换成子查询

explain select tc.* from teachercard tc where  tc.tcid=(
select t.tcid from teacher t where t.tid=(
select c.tid from course c where cname like '%编曲%'
)
)

结果如下

待续。。。

SQL优化笔记一:索引和explain的更多相关文章

  1. SQL优化 MySQL版 - 索引分类、创建方式、删除索引、查看索引、SQL性能问题

    SQL优化 MySQL版  - 索引分类.创建方式.删除索引.查看索引.SQL性能问题 作者 Stanley 罗昊 [转载请注明出处和署名,谢谢!] 索引分类 单值索引 单的意思就是单列的值,比如说有 ...

  2. SQL优化 · 经典案例 · 索引篇

    Introduction 在这些年的工作之中,由于SQL问题导致的数据库故障层出不穷,下面将过去六年工作中遇到的SQL问题总结归类,还原问题原貌,给出分析问题思路和解决问题的方法,帮助用户在使用数据库 ...

  3. oracle sql优化笔记

    oracle优化一般分为:1.sql优化(现在oracle都会根据sql语句先进行必要的优化处理,这种应该用户不大了,但是像关联和嵌套查询肯定是和影响性能的) A.oracle的sql语句的条件是从右 ...

  4. SQL优化基础 使用索引(一个小例子)

    按照本文操作和体会,会对sql优化有个基本最简单的了解,其他深入还需要更多资料和实践的学习: 1. 建表: 复制代码代码如下: create table site_user ( id int IDEN ...

  5. SQL优化笔记—CPU优化

    补充:常规服务器动态管理对象包括,下面有些资料可能会应用到 dm_db_*:数据库和数据库对象dm_exec_*:执行用户代码和关联的连接dm_os_*:内存.锁定和时间安排dm_tran_*:事务和 ...

  6. MySQL SQL优化之字符串索引隐式转换

    之前有用户很不解:SQL语句非常简单,就是select * from test_1 where user_id=1 这种类型,而且user_id上已经建立索引了,怎么还是查询很慢? test_1的表结 ...

  7. sql优化策略之索引失效情况二

    详见: http://blog.yemou.net/article/query/info/tytfjhfascvhzxcytp63   接第一篇索引失效分析:http://grefr.iteye.co ...

  8. SQL优化之慢查询和explain以及性能分析

    性能优化的思路 首先需要使用慢查询功能,去获取所有查询时间比较长的SQL语句 使用explain去查看该sql的执行计划 使用show profile去查看该sql执行时的性能问题 MySQL性能优化 ...

  9. SQL学习笔记

    SQL(Structured Query Language)学习笔记 [TOC] Terminal登录数据库 1.登录mysql -u root -p ; 2.显示所有数据库show database ...

随机推荐

  1. 上传第三方jar包至maven私服,以geotools为例

    上传jar包(模块打包方式为jar) mvn deploy:deploy-file -DgroupId=org.geotools -DartifactId=gt-api -Dversion=10.3 ...

  2. eolinker——分享项目只需两步

    登陆后打开项目概况 然后进入到分享项目界面,可根据自己的需求进行设置

  3. JMeter——JMeter如何进行汉化

    1.找到bin目录下的jmeter.properties文件 2.打开找到第37行,打开注释并将language=en改为language=zh_CN 3.重启

  4. Windows服务一直“正在启动”怎么杀

    转载:https://blog.csdn.net/huanglong8/article/details/71156848 PS:cmd 记得使用 管理员身份运行 这里需要通过控制台 命令行来查询PID ...

  5. LOJ6433 [PKUSC2018] 最大前缀和 【状压DP】

    题目分析: 容易想到若集合$S$为前缀时,$S$外的所有元素的排列的前缀是小于$0$的,DP可以做到,令排列前缀个数小于0的是g[S]. 令f[S]表示$S$是前缀,转移可以通过在前面插入元素完成. ...

  6. 数字平滑 前端插件JS&CSS库

    CDN DEMO 拷贝可用: <!DOCTYPE html> <link rel="stylesheet" href="https://cdn.boot ...

  7. 「AtCoder Grand018A」Getting Difference(GCD)

    题目链接A - Getting Difference 题意 有n(1~\(10^5\))个数\(A_i\) (1~\(10^9\)),每次选两个数,将它们的差的绝对值加入这堆数.问k(1~\(10^9 ...

  8. 「TJOI2015」概率论 解题报告

    「TJOI2015」概率论 令\(f_i\)代表\(i\)个点树形态数量,\(g_i\)代表\(i\)个点叶子个数 然后列一个dp \[ f_i=\sum_{j=0}^{i-1} f_j f_{i-j ...

  9. Paint the Wall ZOJ - 2747

    点数很多,坐标值很大,然后离散化一下用一个点表示一小块的面积对应的颜色,然后更新的时候一块一块更新,查询的时候一块一块查询 #include<map> #include<set> ...

  10. [AH2017/HNOI2017]礼物(FFT)

    题目描述 我的室友最近喜欢上了一个可爱的小女生.马上就要到她的生日了,他决定买一对情侣手 环,一个留给自己,一 个送给她.每个手环上各有 n 个装饰物,并且每个装饰物都有一定的亮度.但是在她生日的前一 ...