当前位置:首页 » 编程语言 » sql面试优化案例
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

sql面试优化案例

发布时间: 2023-04-17 15:16:50

‘壹’ 美团面试题:慢sql有遇到过吗是怎么解决的

大家好,我是田维常,可以叫我老田,也可以叫我田哥

。2017年的时候,我刚去上海,朋友内悄指早推我去美团面试,之前我也写过一个一篇文章,也是在美团面试中遇到的:

美团面试题:String s = new String("111")会创建几个对象?

关于慢SQL,我和面试官扯了很久,面试官也是很谦虚的,总是点头,自己以为回答的还可以。最后的最后,还是说了“ 你先回去等通知吧! ”。

所以,我决定把这个慢SQL技术点,好好和你分享分享。希望你下次在遇到类似的面试,能顺顺利利轻轻松松的斩获自己想要的offer。

MySQL的慢查询日志是MySQL提供的一种日志记录,它用来记录MySQL中查询时间超过(大于)设置阈值(long_query_time)的语句,记录到慢查询日志中。

其中,long_query_time的默认值是10,单位是秒,也就是说默认情况下,你的SQL查询时间超过10秒就算慢SQL了。

在MySQL中,慢SQL日志默认是未开启的,也就说就算出现了慢SQL,也不会告诉你的,如果需要知道哪些SQL是慢SQL,需要我们手动开启慢SQL日志的。

关于慢SQL是否开启,我们可以通过下面这个命令来查看:

在这里插入图片描述

通过命令,我们就可以看到slow_query_log项为OFF,说明我们的慢SQL日志并未开启。另外我们也可以看到我们慢SQL日志存放于哪个目录下和日志文件名。

下面我们来开启慢SQL日志,执行下面的命令:

这里需要注意,这里开启的是我们当前的数据库,并且,我们重启数据库后会失效的。

开启慢SQL日志后,再次查看:


slow_query_log项已经变成ON,说明开启成功。

上面说过慢SQL默认时间是10秒,我们通过下面的命令就可以看到我们慢SQL的默认时间:

在这里插入图片描述

我们总不能一直使用这个默认值,可能很多业务需要时间更短或更长,所以此时,我们就需要对默认时间进行修改,修改命令如下:

修改完了,我们再来看看是否已经改成了3秒。


这里需要注意:想要永久的生效,还需要修改MySQL下面的配置文件my.cnf 文件。

注意:不同操作系统,配置有些区别。

Linux操作系统中

Windows操作系统中

执行一条慢SQL,因为我们前面已经设置好了慢SQL时间为3秒,所以,我们只要执行一条SQL时间超过3秒即可。


该SQL耗时4.024秒,下面我们就来查看慢SQL出现了多少条。

使用命令:


找到慢SQL日志文件,打开后就会出现类似下面这样的语句;

简单说明:

切记

通常我们定位慢SQL有两种方式:

第一种:定位慢查询 SQL 可以通过两个表象进行判断

第二种:根据不同的数据库使用不同的方式获取问题 SQL

如果开启了慢SQL日志后,可能会有大量的慢SQL日志产生,此时再用肉眼看,那是不太现实的,所以大佬们就给我搞了个工具: mysqlmpslow 。

mysqlmpslow 能将相同的慢SQL归类,并统计出相同的SQL执行的次数,每次执行耗时多久、总耗时,每次返回的行数、总行数,以及客户端连接信息等。

通过命令

可以看到相关参数的说明:

比较常用的参数有这么几个:

mysqlmpslow 常用的使用逗庆方式如下:

如上一条命令,应该是mysqlmpslow最简单的一种形式,其中-s参数是以什么方式排序的意思,c指代的是以总数从大到小的方式排序。-s的常用子参数有:c: 相同查询以查询条数和从大到小排序。t: 以查询总时间的方式从大到小排序。l: 以查询锁的总时间的方式从大到小排序。at: 以查询平均时间的方式从大到小排序。al: 以查询锁平均时间的方式从大到启雀小排序。

同样的,还可以增加其他参数,实际使用的时候,按照自己的情况来。

其他常用方式:

接下,我们来个实际操作。

这其中的 SQL 语句因为涉及某些信息,所以我都用*号将主体替换了,如果希望得到具体的值,使用-a参数。

使用 mysqlmpslow 查询出来的摘要信息,包含了这些内容:

Count : 464 :表示慢查询日志总共记录到这条sql语句执行的次数;

Time=18.35s (8515s) :18.35s表示平均执行时间(-s at),8515s表示总的执行时间(-s t);

Lock=0.01s (3s) :与上面的Time相同,第一个表示平均锁定时间(-s al),括号内的表示总的锁定时间(-s l)(也有另一种说法,说是表示的等待锁释放的时间);

Rows=90884.0 (42170176) : 第一个值表示扫描的平均行数(-s ar),括号内的值表示扫描的总行数(-s r)。

是不是

so easy!!!!

‘贰’ 经典sql面试题及答案第10期

create proc 存储过程名

[@参数名 参数类型[, @参数名 参数类型...]]

as

批处理语句

go

alter proc 存储过程名

[@参数名 参数类型[, @参数名 参数类型...]]

as

批处理语句

go

drop proc 存储过程名

exec proc 存储过程名 [参数值[, 参数值...]]

不一样,加括号是执行sql语句,不加括号是执行存储过程。

a. 以Return传回整数

b. 以output格式传回参数

c. Recordset

返回值的区别: output和return都可在批次程式中用变量接收,而recordset则传回到执行批次的客户端中。

create proc queryPage

@tablename nvarchar(50), --用于传入表名

@idname nvarchar(50), --用于传入字段名

@pagesize int, --用于传入每页记录数

@currentpage int, --用于传入希望查看的页面编号

@totalpages int output --用于传出页面总数

as

--声明保存查迟友询语句的局部变量:

declare @sql as nvarchar(1000)

--声明保存记录总码盯槐数的局部变量:

declare @rowcount as int

--获得记录总数:

set @sql='select @rc=count() from '+@tablename --不要直接执行select @rowcount=count() from @tablename

--将参数传入语句:

exec sp_executesql @sql,N'@rc int output',@rc=@rowcount output

--将根据每页的行数得到则拿的总页数保存到输出参数中:

set @totalpages = ceiling(cast(@rowcount as float)/cast(@pagesize as float))

if @currentpage >1

begin if @currentpage>@totalpages

begin set @currentpage = @totalpages --则显示最后一页

end

set @sql = 'select top '+cast(@pagesize as varchar) +' * from '+@tablename+' where '+@idname+' not in (select top ' +cast(@pagesize*(@currentpage-1) as varchar) +' '+@idname+' from '+@tablename+' order by '+@idname+') order by '+@idname

end else --只选第一页就不必使用子查询了,提高性能

begin set @sql = 'select top '+cast(@pagesize as varchar) +' * from '+@tablename+' order by '+@idname

end exec(@sql) --执行查询语句

go

‘叁’ 经典教师 学生 成绩sql面试题再次来袭2(附答案)

点击链接加入QQ群229390571(免费公开课、视频应有尽有): https://jq.qq.com/?_wv=1027&k=5rbudQa

概述

续一下之前讲的sql练习方面内容,怕有行悔些朋友找不到数据,所以这里把建表和准备数据部分也放枯孙着。

建表语句

CREATE TABLE students

(sno VARCHAR(3) NOT NULL,

sname VARCHAR(4) NOT NULL,

ssex VARCHAR(2) NOT NULL,

sbirthday DATETIME,

class VARCHAR(5))

CREATE TABLE courses

(cno VARCHAR(5) NOT NULL,

cname VARCHAR(10) NOT NULL,

tno VARCHAR(10) NOT NULL)

CREATE TABLE scores

(sno VARCHAR(3) NOT NULL,

cno VARCHAR(5) NOT NULL,

degree NUMERIC(10, 1) NOT NULL)

CREATE TABLE teachers

(tno VARCHAR(3) NOT NULL,

tname VARCHAR(4) NOT NULL, tsex VARCHAR(2) NOT NULL,

tbirthday DATETIME NOT NULL, prof VARCHAR(6),

depart VARCHAR(10) NOT NULL)

插入数据

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (108 ,'曾华' ,'男' ,'1977-09-01',95033);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (105 ,'匡明' ,'男' ,'1975-10-02',95031);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (107 ,'王丽' ,'女' ,'1976-01-23',95033);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (101 ,'李军' ,'男' ,'1976-02-20',95033);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (109 ,'王芳' ,'女' ,'1975-02-10',95031);

INSERT INTO STUDENTS (SNO,SNAME,SSEX,SBIRTHDAY,CLASS) VALUES (103 ,'陆君' ,'男' ,'1974-06-03',95031);

INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('3-105'没带链 ,'计算机导论',825);

INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('3-245' ,'操作系统' ,804);

INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('6-166' ,'数据电路' ,856);

INSERT INTO COURSES(CNO,CNAME,TNO)VALUES ('9-888' ,'高等数学' ,100);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (103,'3-245',86);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (105,'3-245',75);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (109,'3-245',68);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (103,'3-105',92);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (105,'3-105',88);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (109,'3-105',76);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (101,'3-105',64);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (107,'3-105',91);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (108,'3-105',78);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (101,'6-166',85);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (107,'6-106',79);

INSERT INTO SCORES(SNO,CNO,DEGREE)VALUES (108,'6-166',81);

INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (804,'李诚','男','1958-12-02','副教授','计算机系');

INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (856,'张旭','男','1969-03-12','讲师','电子工程系');

INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (825,'王萍','女','1972-05-05','助教','计算机系');

INSERT INTO TEACHERS(TNO,TNAME,TSEX,TBIRTHDAY,PROF,DEPART) VALUES (831,'刘冰','女','1977-08-14','助教','电子工程系');

题目(先思考如何实现)

1、查询所有学生的Sname、Cname和Degree列。

2、查询“95033”班所选课程的平均分。

3、假设使用如下命令建立了一个grade表:

create table grade(low number(3,0),upp number(3),rank char(1));

insert into grade values(90,100,’A’);

insert into grade values(80,89,’B’);

insert into grade values(70,79,’C’);

insert into grade values(60,69,’D’);

insert into grade values(0,59,’E’);

commit;

现查询所有同学的Sno、Cno和rank列。

4、查询选修“3-105”课程的成绩高于“109”号同学成绩的所有同学的记录。

5、查询score中选学一门以上课程的同学中分数为非最高分成绩的记录。

6、查询成绩高于学号为“109”、课程号为“3-105”的成绩的所有记录。

7、查询和学号为108的同学同年出生的所有学生的Sno、Sname和Sbirthday列。

8、查询“张旭“教师任课的学生成绩。

9、查询选修某课程的同学人数多于5人的教师姓名。

10、查询95033班和95031班全体学生的记录。

11、查询存在有85分以上成绩的课程Cno.

12、查询出“计算机系“教师所教课程的成绩表。

13、查询“计算机系”与“电子工程系“不同职称的教师的Tname和Prof。

14、查询选修编号为“3-105“课程且成绩至少高于选修编号为“3-245”的同学的Cno、Sno和Degree,并按Degree从高到低次序排序。

15、查询选修编号为“3-105”且成绩高于选修编号为“3-245”课程的同学的Cno、Sno和Degree.

答案

1.查询所有学生的Sname、Cname和Degree列。

SELECT Sname,Cname,Degree

FROM Students INNER JOIN Scores

ON(Students.Sno=Scores.Sno) INNER JOIN Courses

ON(Scores.Cno=Courses.Cno)

ORDER BY Sname;

2.查询“95033”班所选课程的平均分。

SELECT Cname,AVG(Degree)

FROM Students INNER JOIN Scores

ON(Students.Sno=Scores.Sno) INNER JOIN Courses

ON(Scores.Cno=Courses.Cno)

WHERE Class='95033'

GROUP BY Courses.Cno

ORDER BY Cname;

3.假设使用如下命令建立了一个grade表:

CREATE TABLE grade(low TINYINT,upp TINYINT,rank CHAR(1));

INSERT INTO grade VALUES(90,100,'A');

INSERT INTO grade VALUES(80,89,'B');

INSERT INTO grade VALUES(70,79,'C');

INSERT INTO grade VALUES(60,69,'D');

INSERT INTO grade VALUES(0,59,'E');

现查询所有同学的Sno、Cno和rank列。

SELECT Sno,Cno,rank

FROM Scores INNER JOIN grade

ON(Scores.Degree>=grade.low AND Scores.Degree<=grade.upp)

ORDER BY Sno;

4.查询选修“3-105”课程的成绩高于“109”号同学成绩的所有同学的记录。

SELECT s1.Sno,s1.Degree

FROM Scores AS s1 INNER JOIN Scores AS s2

ON(s1.Cno=s2.Cno AND s1.Degree>s2.Degree)

WHERE s1.Cno='3-105' AND s2.Sno='109'

ORDER BY s1.Sno;

5.查询score中选学一门以上课程的同学中分数为非最高分成绩的记录。

SELECT *

FROM Scores

GROUP BY Sno

HAVING COUNT(cno)>1 AND Degree!=MAX(Degree);

6.查询成绩高于学号为“109”、课程号为“3-105”的成绩的所有记录。

SELECT s1.Sno,s1.Degree

FROM Scores AS s1 INNER JOIN Scores AS s2

ON(s1.Cno=s2.Cno AND s1.Degree>s2.Degree)

WHERE s1.Cno='3-105' AND s2.Sno='109'

ORDER BY s1.Sno;

7.查询和学号为108的同学同年出生的所有学生的Sno、Sname和Sbirthday列。

SELECT s1.Sno,s1.Sname,s1.Sbirthday

FROM Students AS s1 INNER JOIN Students AS s2

ON(YEAR(s1.Sbirthday)=YEAR(s2.Sbirthday))

WHERE s2.Sno='108';

8.查询“张旭“教师任课的学生成绩。

SELECT Sno,Degree

FROM Scores INNER JOIN Courses

ON(Scores.Cno=Courses.Cno) INNER JOIN Teachers

ON(Courses.Tno=Teachers.Tno)

WHERE Teachers.Tname='张旭';

9.查询选修某课程的同学人数多于5人的教师姓名。

SELECT DISTINCT Tname

FROM Scores INNER JOIN Courses

ON(Scores.Cno=Courses.Cno) INNER JOIN Teachers

ON(Courses.Tno=Teachers.Tno)

WHERE Courses.Cno IN(SELECT Cno FROM Scores GROUP BY(Cno) HAVING COUNT(Sno)>5);

10.查询95033班和95031班全体学生的记录。

SELECT *

FROM Students

WHERE Class IN ('95033','95031')

ORDER BY Class;

11.查询存在有85分以上成绩的课程Cno.

SELECT DISTINCT Cno FROM Scores WHERE Degree>85;

12.查询出“计算机系“教师所教课程的成绩表。

SELECT Tname,Cname,SName,Degree

FROM Teachers INNER JOIN Courses

ON(Teachers.Tno=Courses.Tno) INNER JOIN Scores

ON(Courses.Cno=Scores.Cno) INNER JOIN Students

ON(Scores.Sno=Students.Sno)

WHERE Teachers.Depart='计算机系'

ORDER BY Tname,Cname,Degree DESC;

13.查询“计算机系”与“电子工程系“不同职称的教师的Tname和Prof。

SELECT Tname,Prof

FROM Teachers

WHERE Depart='计算机系' AND Prof NOT IN(

SELECT DISTINCT Prof

FROM Teachers

WHERE Depart='电子工程系');

14.查询选修编号为“3-105“课程且成绩至少高于任意选修编号为“3-245”的同学的成绩的Cno、Sno和Degree,并按Degree从高到低次序排序。

SELECT Cno,Sno,Degree

FROM Scores

WHERE Cno='3-105' AND Degree > ANY(

SELECT Degree

FROM Scores

WHERE Cno='3-245')

ORDER BY Degree DESC;

15.查询选修编号为“3-105”且成绩高于所有选修编号为“3-245”课程的同学的Cno、Sno和Degree.

SELECT Cno,Sno,Degree

FROM Scores

WHERE Cno='3-105' AND Degree > ALL(

SELECT Degree

FROM Scores

WHERE Cno='3-245')

ORDER BY Degree DESC;

以上仅为参考答案

‘肆’ 关于Oracle PL/SQL优化,一面试题,求助

应该是说结构不是固定的,可能数据库存在1000个表,每个需求不同,因此不能定义临时表来存个储这样。记得不太清楚了,应该是靠怎样避免重复创建表吧。
就算结构是灵活的,也可以定义临时表,多定义几个就是。

‘伍’ 面试题_说说你是怎么数据库优化的

对sql语句优化:


就是能分开写的语句就分开写,不要一次性就解决,这样对效率来说是很大的开销的


避免使用不兼容伍腊的数据类型:


如float和int,char和varchar等都是不兼容的。



尽量避免在where子句中对字段进行函孙橘物数或表达式操作
避免使用isnotnull、in等一些无法让系统使用索引操作的词
合理使用exists,notexists字句
尽量则液避免在索引过的字符数据中,使用非打头字母所有
避免困难的正规表达式


对mysql优化:





1.选取最适用的字段属性,可以的情况下,应该尽量把字段设置为NOTNULL


2.使用连接(JOIN)来代替子查询


3.使用联合来代替手动创建的临时表


4.增删改或者多条查询数据时使用事务操作


5.锁定表(代替事务的另一种方法)


6.使用外键(锁定表的方法可以维护数据的完整性,但它不能保证数据的关联性,应该使用外键)


7.可以优化SQL查询算法,提高查询速度8.给数据量大的查询次数频繁而修改次数少的数据表添加索引,提升查询速度



面试题_说说你是怎么数据库优化的
标签:锁定oat试题数据表arc手动频繁添加设置


‘陆’ 这些SQL优化技巧握在手,面试可以横着走……

一、SQL执行顺序



二、基础SQL优化


1、查询SQL尽量不要使用select *,而是具体字段


1)反例



2)正例



3)理由



2、避免在where子句中使用or来连接条件


查询id为1或者薪水为3000的用户:


1)反例



2)正例


使用union all:



分开两条SQL写:



3)理由



3、使用varchar代替char


1)反例



2)正例



3)理由



4、尽量使用数值替代字符串类型



5、查询尽量避免返回大量数据


如果查询返回数据量很大,就会造成查询时间过长,网络传输时间过长。同时,大量数据返回也可能没有实际意义。如返回上千条甚至更多,用户也看不过来。

通常采用分页,一页习惯10/20/50/100条。


6、使用explain分析你SQL执行计划


SQL很灵活,一个需求可以很多实现,那哪个最优呢?SQL提供了explain关键字,它可以分析你的SQL执行计划,看它是否最佳。Explain主要看SQL是否使用了索引。



返回结果:



7、是否使用了索引及其扫描类型


type:



性能排行:


System > const > eq_ref > ref > range > index > ALL


possible_keys:



key:



8、创建name字段的索引


提高查询速度的最简单最佳的方式。



9、优化like语句


模糊查询,程序员最喜欢的就是使用like,但是like很可能让你的索引失效。


1)反例



2)正例



3)理由


未使用索引,故意使用sex非索引字段:




主键索引生效:




索引失效,type=ALL,全表扫描:




10、字符串怪现象


1)反例



2)正例



3)理由


为什么第一条语句未加单引号就不走索引了呢?这是因为不加单引号时,是字符串跟数字的比较,它们类型不匹配,MySQL会做隐式的类型转换,把它们转换为数值类型再做比较。


11、索引不宜太多,一般5个以内



12、索引不适合建在有大量重复数据的字段上


如性别字段。因为SQL优化器是根据表中数据量来进行查询优化的,如果索引列有大量重复数据,Mysql查询优化器推算发现不走索引的成本更低,很可能就放弃索引了。


13、where限定查询的数据


数据中假定就一个男的记录。


1)反例



2)正例



3)理由



14、避免在索引列上使用内置函数


业务需求:查询最近七天内新生儿(用学生表替代下)


给birthday字段创建索引:



当前时间加7天:



1)反例



2)正例



3)理由







15、避免在where中对字段进行表达式操作


1)反例



2)正例




3)理由






16、避免在where子句中使用!=或>操作符


应尽量避免在where子句中使用!=或>操作符,否则引擎将放弃使用索引而进行全表扫描。记住实现业务优先,实在没办法,就只能使用,并不是不能使用。如果不能使用,SQL也就无需支持了。


1)反例




2)理由




17、去重distinct过滤字段要少





1)理由


18、where中使用默认值代替null


环境准备:




1)反例



2)正例



3)理由



三、高级SQL优化


1、批量插入性能提升


大量数据提交,上千,上万,批量性能非常快,mysql独有。


1)多条提交



2)批量提交



3)理由



2、批量删除优化


避免同时修改或删除过多数据,因为会造成cpu利用率过高,会造成锁表操作,从而影响别人对数据库的访问


1)反例




2)正例




3)理由



3、伪删除设计


1)商品状态(state)



2)理由



4、提高group by语句的效率


可以在执行到该语句前,把不需要的记录过滤掉。


1)反例:先分组,再过滤



2)正例:先过滤,后分组



5、复合索引最左特性


创建复合索引,也就是多个字段。



满足复合索引的左侧顺序,哪怕只是部分,复合索引生效。



没有出现左边的字段,则不满足最左特性,索引失效。



复合索引全使用,按左侧顺序出现 name,salary,索引生效。



虽然违背了最左特性,但MYSQL执行SQL时会进行优化,底层进行颠倒优化。



1)理由



6、排序字段创建索引


什么样的字段才需要创建索引呢?原则就是where和order by中常出现的字段就创建索引。



7、删除冗余和重复的索引




8、不要有超过5个以上的表连接



9、inner join 、left join、right join,优先使用inner join


三种连接如果结果相同,优先使用inner join,如果使用left join左边表尽量小。



1)理由



10、in子查询的优化


日常开发实现业务需求可以有两种方式实现:



如需求:查询所有部门的所有员工:



假设表A表示某企业的员工表,表B表示部门表,查询所有部门的所有员工,很容易有以下程序实现,可以抽象成这样的一个嵌套循环:


‘柒’ 搞定这30个SQL面试问题,助你成功升级面霸

CREATE VIEW view_name AS

SELECT column_name1, column_name2

FROM table_name

WHERE CONDITION;

我们一起分享AI学习与发展的干货

欢迎竖局关注全平台AI垂类余液让自媒体 “读埋闷芯术”

‘捌’ SQL优化万能公式:5 大步骤 + 10 个案例

在应用开发的早期,数据量少,开发人员开发功能时更重视功能上的实现,随着生产数据的增长,很多SQL语句开始暴露出性能问题,对生产的影响也越来越大,有时可能这些有问题的SQL就是整个系统性能的瓶颈。

1、通过慢查日志等定位那些执行效率较低的SQL语句

2、explain 分析SQL的执行计划

type由上至下,效率越来越高

Extra

3、show profile 分析

了解SQL执行的线程的状态及消耗的时间。默认是关闭的,开启语句“set profiling = 1;”

4、trace

trace分析优化器如何选择执行计划,通过trace文件能够进一步了解为什么优惠券选择A执行计划而不选择B执行计划。

5、确定问题并采用相应的措施

案例1、最左匹配

索引

SQL语句

查询匹配从左往右匹配,要使用order_no走索引,必须查询条件携带shop_id或者索引( shop_id , order_no )调换前后顺序

案例2、隐式转换

索引

SQL语句

隐式转换相当于在索引上做运算,会让索引失效。mobile是字符类型,使用了数字,应该使用字符串匹配,否则MySQL会用到隐式替换,导致索引失效。

案例3、大分页

索引

SQL语句

对于大分页的场景,可以优先让产品优化需求,如果没有优化的,有如下两种优化方式, 一种是把上一次的最后一条数据,也即上面的c传过来,然后做“c < xxx”处理,但是这种一般需要改接口协议,并不一定可行。另一种是采用延迟关联的方式进行处理,减少SQL回表,但是要记得索引需要完全覆盖才有效果,SQL改动如下

案例4、in + order by

索引

SQL语句

in查询在MySQL底层是通过n*m的方式去搜索,类似union,但是效率比union高。in查询在进行cost代价计算时(代价 = 元组数 * IO平均值),是通过将in包含的数值,一条条去查询获取元组数的,因此这个计算过程会比较的慢,所以MySQL设置了个临界值(eq_range_index_pe_limit),5.6之后超过这个临界值后该列的cost就不参与计算了。因此会导致执行计划选择不准确。默认是200,即in条件超过了200个数据,会导致in的代价计算存在问题,可能会导致Mysql选择的索引不准确。

处理方式,可以( order_status , created_at )互换前后顺序,并且调整SQL为延迟关联。

案例5、范围查询阻断,后续字段不能走索引

索引

SQL语句

范围查询还有“IN、between”

案例6、不等于、不包含不能用到索引的快速搜索。(可以用到ICP)

在索引上,避免使用NOT、!=、>、!、NOT EXISTS、NOT IN、NOT LIKE等

案例7、优化器选择不使用索引的情况

如果要求访问的数据量很小,则优化器还是会选择辅助索引,但是当访问的数据占整个表中数据的蛮大一部分时(一般是20%左右),优化器会选择通过聚集索引来查找数据。

查询出所有未支付的订单,一般这种订单是很少的,即使建了索引,也没法使用索引。

案例8、复杂查询

如果是统计某些数据,可能改用数仓进行解决;如果是业务上就有那么复杂的查询,可能就不建议继续走SQL了,而是采用其他的方式进行解决,比如使用ES等进行解决。

案例9、asc和desc混用

desc 和asc混用时会导致索引失效

案例10、大数据

对于推送业务的数据存储,可能数据量会很大,如果在方案的选择上,最终选择存储在MySQL上,并且做7天等有效期的保存。那么需要注意,频繁的清理数据,会照成数据碎片,需要联系DBA进行数据碎片处理。

‘玖’ 几个面试中遇到的SQL题,大家帮帮忙

1,select * from pages where url='..' union all
select * from pages where title='...' union all
select * from pages where body='...'
2,select case when a>b then a when b<=c then c else b end from 表
3,A表建触发器
CREATE TRIGGER myt
ON 表A
FOR UPDATE
AS
If UPDATE(主键)
BEGIN
update b
set 同字段1=a.同字段1,同字段2=a.同字段2
from 表B b,inserted a
where b.主键=a.主键
END

‘拾’ sql优化的几种方法面试

1.你把学校里面学的东西都弄通,弄懂就可以了,基本的概念和原理都能说出来,如你说的sql优化就是:为数据库建立索引,如何提高检索速度之类的问题。教科书上都有说啊。
2.面试不是说一定要什么都懂才能去面的,你要找多一点面试经验,面试经常问什么问题,比如指针,链表等,有针对性地准备一下,不用全部一骨碌地看。
3.积累经验和编程作品,多做项目,自己多写些程序。面试就有了筹码。