• 企业面试题|最常问的MySQL面试题集合(二)


    MySQL的关联查询语句

    六种关联查询

    • 交叉连接(CROSS JOIN)

    • 内连接(INNER JOIN)

    • 外连接(LEFT JOIN/RIGHT JOIN)

    • 联合查询(UNION与UNION ALL)

    • 全连接(FULL JOIN)

    • 交叉连接(CROSS JOIN)

    SELECT * FROM A,B(,C)或者
    SELECT * FROM A CROSS JOIN B (CROSS JOIN C)
    #没有任何关联条件,结果是笛卡尔积,结果集会很大,没有意义,很少使用
    内连接(INNER JOIN)
    SELECT * FROM A,B WHERE A.id=B.id或者
    SELECT * FROM A INNER JOIN B ON A.id=B.id
    多表中同时符合某种条件的数据记录的集合,INNER JOIN可以缩写为JOIN

    内连接分为三类

    • 等值连接:ON A.id=B.id

    • 不等值连接:ON A.id > B.id

    • 自连接:SELECT * FROM A T1 INNER JOIN A T2 ON T1.id=T2.pid

    外连接(LEFT JOIN/RIGHT JOIN)

    • 左外连接:LEFT OUTER JOIN, 以左表为主,先查询出左表,按照ON后的关联条件匹配右表,没有匹配到的用NULL填充,可以简写成LEFT JOIN

    • 右外连接:RIGHT OUTER JOIN, 以右表为主,先查询出右表,按照ON后的关联条件匹配左表,没有匹配到的用NULL填充,可以简写成RIGHT JOIN

    联合查询(UNION与UNION ALL)

    SELECT * FROM A UNION SELECT * FROM B UNION ...
    • 就是把多个结果集集中在一起,UNION前的结果为基准,需要注意的是联合查询的列数要相等,相同的记录行会合并

    • 如果使用UNION ALL,不会合并重复的记录行

    • 效率 UNION 高于 UNION ALL

    全连接(FULL JOIN)

    • MySQL不支持全连接

    • 可以使用LEFT JOIN 和UNION和RIGHT JOIN联合使用

    SELECT * FROM A LEFT JOIN B ON A.id=B.id UNION
    SELECT * FROM A RIGHT JOIN B ON A.id=B.id

    嵌套查询
    用一条SQL语句得结果作为另外一条SQL语句得条件,效率不好把握
    SELECT * FROM A WHERE id IN (SELECT id FROM B)

    解题方法

    根据考题要搞清楚表的结果和多表之间的关系,根据想要的结果思考使用那种关联方式,通常把要查询的列先写出来,然后分析这些列都属于哪些表,才考虑使用关联查询

    问题20:
    为了记录足球比赛的结果,设计表如下:
    team:参赛队伍表
    match:赛程表
    其中,match赛程表中的hostTeamID与guestTeamID都和team表中的teamID关联,查询2006-6-1到2006-7-1之间举行的所有比赛,并且用以下形式列出:拜仁 2:0 不莱梅 2006-6-21

    首先列出需要查询的列:
    • 表team

    • teamID teamName

    • 表match

    • match ID

    • hostTeamID

    • guestTeamID

    • matchTime matchResult

    其次列出结果列:
    • 主队 结果 客对 时间

    初步写一个基础的SQL:

    SELECT hostTeamID,matchResult,matchTime guestTeamID from match where matchTime between "2006-6-1" and "2006-7-1";

    通过外键联表,完成最终SQL:

    select t1.teamName,m.matchResult,t2.teamName,m.matchTime from match as m left join team as t1 on m.hostTeamID = t1.teamID, left join team t2 on m.guestTeamID=t2.guestTeamID where m.matchTime between "2006-6-1" and "2006-7-1"

    问题21:UNION与UNION ALL的区别?

    • 如果使用UNION ALL,不会合并重复的记录行

    • 效率 UNION 高于 UNION ALL

    问题22:一个6亿的表a,一个3亿的表b,通过外键tid关联,你如何最快的查询出满足条件的第50000到第50200中的这200条数据记录。

    • 1、如果A表TID是自增长,并且是连续的,B表的ID为索引

    select * from a,b where a.tid = b.id and a.tid>50000 limit 200;
    • 2、如果A表的TID不是连续的,那么就需要使用覆盖索引.TID要么是主键,要么是辅助索引,B表ID也需要有索引。

    select * from b , (select tid from a limit 50000,200) a where b.id = a .tid;

    问题23:拷贝表( 拷贝数据, 源表名:a 目标表名:b)

    insert into b(a, b, c) select d,e,f from a;

    问题24: Student(S#,Sname,Sage,Ssex) 学生表 Course(C#,Cname,T#) 课程表 SC(S#,C#,score) 成绩表 Teacher(T#,Tname) 教师表 查询没学过“叶平”老师课的同学的学号、姓名

    select Student.S#,Student.Sname
    from Student
    where S# not in (select distinct( SC.S#) from SC,Course,Teacher where SC.C#=Course.C# and Teacher.T#=Course.T# and Teacher.Tname=’叶平’);

    问题25:随机取出10条数据

    SELECT * FROM users WHERE id >= ((SELECT MAX(id) FROM users)-(SELECT MIN(id) FROM users)) * RAND() + (SELECT MIN(id) FROM users) LIMIT 10
    #此方法效率比直接用SELECT * FROM users order by rand() LIMIT 10高很多

    问题26:请简述项目中优化SQL语句执行效率的方法,从哪些方面,SQL语句性能如何分析?
    考点分析:
    这道题主要考察的是查找分析SQL语句查询速度慢的方法
    延伸考点:

    • 优化查询过程中的数据访问

    • 优化长难的查询语句

    • 优化特定类型的查询语句

    如何查找查询速度慢的原因
    记录慢查询日志,分析查询日志,不要直接打开慢查询日志进行分析,这样比较浪费时间和精力,可以使用pt-query-digest工具进行分析

    使用show profile
    set profiling=1;开启,服务器上所有执行语句会记录执行时间,存到临时表中
    show profiles
    show profile for query 临时表ID
    使用show status

    show status会返回一些计数器,show global status会查看所有服务器级别的所有计数
    有时根据这些计数,可以推测出哪些操作代价较高或者消耗时间多

    show processlist

    观察是否有大量线程处于不正常的状态或特征

    最常问的MySQL面试题五——每个开发人员都应该知道

    使用explain

    分析单条SQL语句

    优化查询过程中的数据访问

    • 访问数据太多导致查询性能下降

    • 确定应用程序是否在检索大量超过需要的数据,可能是太多行或列

    • 确认MySQL服务器是否在分析大量不必要的数据行

    • 避免犯如下SQL语句错误

    • 查询不需要的数据。解决办法:使用limit解决

    • 多表关联返回全部列。解决办法:指定列名

    • 总是返回全部列。解决办法:避免使用SELECT *

    • 重复查询相同的数据。解决办法:可以缓存数据,下次直接读取缓存

    • 是否在扫描额外的记录。解决办法:

    • 使用explain进行分析,如果发现查询需要扫描大量的数据,但只返回少数的行,可以通过如下技巧去优化:

    • 使用索引覆盖扫描,把所有的列都放到索引中,这样存储引擎不需要回表获取对应行就可以返回结果。

    • 改变数据库和表的结构,修改数据表范式

    • 重写SQL语句,让优化器可以以更优的方式执行查询。

    优化长难的查询语句

    • 一个复杂查询还是多个简单查询

    • MySQL内部每秒能扫描内存中上百万行数据,相比之下,响应数据给客户端就要慢得多

    • 使用尽可能小的查询是好的,但是有时将一个大的查询分解为多个小的查询是很有必要的。

    • 切分查询

    • 将一个大的查询分为多个小的相同的查询

    • 一次性删除1000万的数据要比一次删除1万,暂停一会的方案更加损耗服务器开销。

    • 分解关联查询,让缓存的效率更高。

    • 执行单个查询可以减少锁的竞争。

    • 在应用层做关联更容易对数据库进行拆分。

    • 查询效率会有大幅提升。

    • 较少冗余记录的查询。

    优化特定类型的查询语句

    • count(*)会忽略所有的列,直接统计所有列数,不要使用count(列名)

    • MyISAM中,没有任何where条件的count(*)非常快。

    • 当有where条件时,MyISAM的count统计不一定比其它引擎快。

    • 可以使用explain查询近似值,用近似值替代count(*)

    • 增加汇总表

    • 使用缓存

    优化关联查询

    • 确定ON或者USING子句中是否有索引。

    • 确保GROUP BY和ORDER BY只有一个表中的列,这样MySQL才有可能使用索引。

    优化子查询

    • 用关联查询替代

    • 优化GROUP BY和DISTINCT

    • 这两种查询据可以使用索引来优化,是最有效的优化方法

    • 关联查询中,使用标识列分组的效率更高

    • 如果不需要ORDER BY,进行GROUP BY时加ORDER BY NULL,MySQL不会再进行文件排序。

    • WITH ROLLUP超级聚合,可以挪到应用程序处理

    优化LIMIT分页

    • LIMIT偏移量大的时候,查询效率较低

    • 可以记录上次查询的最大ID,下次查询时直接根据该ID来查询

    优化UNION查询

    • UNION ALL的效率高于UNION

    优化WHERE子句

    解题方法

    对于此类考题,先说明如何定位低效SQL语句,然后根据SQL语句可能低效的原因做排查,先从索引着手,如果索引没有问题,考虑以上几个方面,数据访问的问题,长难查询句的问题还是一些特定类型优化的问题,逐一回答。

    SQL语句优化的一些方法?

    • 1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。

    • 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索引而进行全表扫描,如:

    select id from t where num is null可以在num上设置默认值0,确保表中num列没有null值,然后这样查询:select id from t where num=
    • 3.应尽量避免在 where 子句中使用!=或<>操作符,否则引擎将放弃使用索引而进行全表扫描。

    • 4.应尽量避免在 where 子句中使用or 来连接条件,否则将导致引擎放弃使用索引而进行全表扫描,如:

    select id from t where num=10 or num=20可以这样查询:select id from t where num=10 union all select id from t where num=20
    • 5.in 和 not in 也要慎用,否则会导致全表扫描,如:

    select id from t where num in(1,2,3) 对于连续的数值,能用 between 就不要用 in 了:select id from t where num between and 3
    • 6.下面的查询也将导致全表扫描:select id from t where name like ‘%李%’若要提高效率,可以考虑全文检索。

    • 7. 如果在 where 子句中使用参数,也会导致全表扫描。因为SQL只有在运行时才会解析局部变量,但优化程序不能将访问计划的选择推迟到运行时;它必须在编译时进行选择。然 而,如果在编译时建立访问计划,变量的值还是未知的,因而无法作为索引选择的输入项。如下面语句将进行全表扫描:

    select id from t where num=@num可以改为强制查询使用索引:select id from t with(index(索引名)) where num=@num
    • 8.应尽量避免在 where 子句中对字段进行表达式操作,这将导致引擎放弃使用索引而进行全表扫描。如:

    select id from t where num/2=100应改为:select id from t where num=100*2
    • 9.应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。如:

    select id from t where substring(name,1,3)=’abc’ ,name以abc开头的id应改为:
    select id from t where name like ‘abc%’
    • 10.不要在 where 子句中的“=”左边进行函数、算术运算或其他表达式运算,否则系统将可能无法正确使用索引。

  • 相关阅读:
    C. Shaass and Lights 解析(思維、組合)
    D. Binary String To Subsequences(队列)(贪心)
    CodeForces 1384B2. Koa and the Beach (Hard Version)(贪心)
    CodeForces 1384B1. Koa and the Beach (Easy Version)(搜索)
    CodeForces 1384C. String Transformation 1(贪心)(并查集)
    CodeForces 1384A. Common Prefixes
    POJ-2516 Minimum Cost(最小费用最大流)
    POJ3261-Milk Patterns(后缀数组)
    HDU-1300 Pearls(斜率DP)
    HDU-4528 小明系列故事-捉迷藏(BFS)
  • 原文地址:https://www.cnblogs.com/duanlinxiao/p/10923051.html
Copyright © 2020-2023  润新知