SQL常见面试题总结1V:https://developer.aliyun.com/article/1473882
请说出sql语句中 left join ,inner join 和right join的区别
left join(左联接) :返回包括左表中的所有记录和右表中联结字段相等的记录
right join(右联接) :返回包括右表中的所有记录和左表中联结字段相等的记录
inner join(等值连接) :只返回两个表中联结字段相等的行
分库分表的问题如何实现分布式全局唯一ID
在分库分表的环境中,数据分布在不同的分片上,不能再借助数据库自增长特性直接生成,否则会造成不同分片上的数据表主键会重复。
Group By和Order By
GROUP BY 和 ORDER BY同时使用的方法及注意事项:
GROUP BY和ORDER BY同时存在的情况是,ORDER BY对GROUP BY后的结果再进行排序,所以ORDER BY后面的排序字段需要在SELECT里出现,ORDER BY 子句中的列必须包含在聚合函数或 GROUP BY 子句中
where和having子句的区别
having和where的区别:
作用的对象不同。WHERE 子句作用于表和视图,HAVING 子句作用于组。
WHERE 在分组和聚集计算之前选取输入行(因此,它控制哪些行进入聚集计算), 而 HAVING 在分组和聚集之后选取分组的行。因此,WHERE 子句不能包含聚集函数; 因为试图用聚集函数判断那些行输入给聚集运算是没有意义的。 相反,HAVING 子句总是包含聚集函数。(严格说来,你可以写不使用聚集的 HAVING 子句, 但这样做只是白费劲。同样的条件可以更有效地用于 WHERE 阶段。)
WHERE不需要聚集。 这样比在 HAVING 里增加限制更加高效,因为我们避免了为那些未通过 WHERE 检查的行进行分组和聚集计算
综上所述:
having一般跟在group by之后,执行记录组选择的一部分来工作的。
where则是执行所有数据来工作的。
再者having可以用聚合函数,如having sum(qty)>1000
SQL优化
- 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引。
- 应尽量避免在 where 子句中使用 or 来连接条件, 用 union all来代替
应尽量避免在where子句中对字段进行函数操作,这将导致引擎放弃使用索引而进行全表扫描。
不要写一些没有意义的查询,如需要生成一个空表结构
索引并不是越多越好,索引固然可以提高相应的 select 的效率,但同时也降低了 insert 及 update 的效率,
innodb引擎下,尽可能的使用 varchar 代替 char ,因为varchar长度可变。
尽量避免向客户端返回大数据量,若数据量过大,应该考虑相应需求是否合理。
MySQL优化
- 创建索引
- 复合索引
- 索引不会包含有NULL值的列
- 使用短索引
- 排序的索引问题
- like语句操作
- 不要在列上进行运算
- 不使用NOT IN和<>操作
索引
索引是为了加速对表中数据行的检索而创建的一种分散的存储结构实现原理(B+树) 通俗点说类似于一本书的目录,通过目录可以快速查到你想要的数据。
索引有什么用
索引能大幅度提高查询效率
但是数据的变更(增删改)都需要维护索引,因此更多的索引意味着更多的维护成本
更多的索引意味着也需要更多的空间 (就比如说一本100页的书,却有50页目录)
过小的表,建索引还可能会更慢(就比如说读个2页的宣传手册,你还先去找目录)
索引的优缺点
- 索引的优点:创建唯一性索引,保证数据库表中每一行数据的唯一性
- 大大加快数据的检索速度,这也是创建索引的最主要的原因
- 加速表和表之间的连接,特别是在实现数据的参考完整性方面特别有意义。
- 在使用分组和排序子句进行数据检索时,同样可以显著减少查询中分组和排序的时间。
- 通过使用索引,可以在查询的过程中使用优化隐藏器,提高系统的性能。
- 索引的缺点:
- 创建索引和维护索引要耗费时间,这种时间随着数据量的增加而增加
- 索引需要占物理空间,除了数据表占数据空间之外,每一个索引还要占一定的物理空间,如果要建立聚簇索引,那么需要的空间就会更大
- 当对表中的数据进行增加、删除和修改的时候,索引也要动态的维护,降低了数据的维护速度
事物的特性有哪些
- 原子性 (atomicity):强调事务的不可分割.
- 一致性 (consistency):事务的执行的前后数据的完整性保持一致.
- 隔离性 (isolation):一个事务执行的过程中,不应该受到其他事务的干扰
- 持久性(durability) :事务一旦结束,数据就持久到数据库
什么是事务
数据库事务是指作为单个逻辑工作单元执行的一系列操作(SQL语句)。这些操作要么全部执行,要么全部不执行。
为什么需要事务
经典的银行转账行为,A账户转给B账户10元,数据库操作需要两步,第一步A账户减10元,第二步B账户加10元,如果没有事务并且在两步中间发生异常,就会导致A的账户少了10元,但B的账户没有变化,如果不能保证这两步操作统一,银行的转账业务也没法进行展开了。
count(*)和count(1)有什么区别
count(1) 含义
count(1) 会统计表中的所有的记录数,包含字段为null 的记录
count(1)指的并不是计算1的个数,而是指表的第一个字段
用count对字段为null的数据可以查出来吗
不可以
对于返回的结果集,一行行地判断,如果 count 函数的参数不是 NULL,累计值就加 1,否则不加。最后返回累计值
count(*)和count(1)哪个执行效率高
如果count(1)是聚索引 id,那肯定是count(1)快
执行效果上
count(*)包括了所有的列,相当于行数,在统计结果的时候,不会忽略列值为NULL
count(1)包括了忽略所有列,用1代表代码行,在统计结果的时候,不会忽略列值为NULL
count(列名)只包括列名那一列,在统计结果的时候,会忽略列值为空(这里的空不是只空字符串或者0,而是表示null)的计数,即某个字段值为NULL时,不统计
执行效率上
列名为主键,count(列名)会比count(1)快
列名不为主键,count(1)会比count(列名)快
如果表多个列并且没有主键,则 count(1) 的执行效率优于 count ( * )
如果有主键,则 select count(主键)的执行效率是最优的
如果表只有一个字段,则 select count ( * )最优
MySQL 的全局锁、表锁和行锁
行级锁(row-level locking)是Mysql中锁定粒度最细的一种锁,表示只针对当前操作的行进行加锁。行级锁能大大减少数据库操作的冲突。其加锁粒度最小,但加锁的开销也最大。
表级锁(table-level locking)是MySQL中锁定粒度最大的一种锁,表示对当前操作的整张表加锁,它实现简单,资源消耗较少,被大部分MySQL引擎支持。最常使用的MYISAM与INNODB都支持表级锁。
全局锁
全局锁就是对整个数据库实例加锁,mysql提供了一个加全局读锁的方法,命令是flush tables with read lock。让你需要让整个库处于只读状态的时候,可以使用这个命令,之后其他线程的语句都会被阻塞:
- 数据更新语句(数据的增删改)
- 数据定义语句(包括建表、修改表结构等)
- 更新类事务的提交语句
全局锁使用场景: 全库逻辑备份
表级锁
mysql里面表级别的锁有两种:一种是表锁,一种是元数据锁(meta data lock,MDL)
表锁的语法是lock tables …read/write,与ftwrl类似,可以用unlock tables 主动释放锁,也可以在客户端断开的时候自动释放。需要注意,lock tables语法除了会限制别的线程的读写外,也限定了本线程接下来的操作对象。
另一个表级锁是MDL,元数据锁,这个锁在访问一个表时自动进行加上,防止读写不正确。
行锁
行锁就是针对数据表中行记录的锁,比如事务A更新了一行,而这时候事务B也要更新一行,则必须等事务A的操作完成后才能进行更新。
死锁和死锁检测
当并发系统中不同线程出现循环资源依赖,涉及的线程都在等待别的线程释放资源时,就会导致这几个线程都进入无限等待的状态,称为死锁。
当出现死锁以后,有两种策略:
一种策略是,直接进入等待,直至超时。这个超时时间可以通过参数innodb_lock_wait_timeout来设置
另一种策略是,发起死锁检测,发现死锁后,主动回滚死锁链条中的某一个事务,让其他事务得以继续执行,将参数innodb_deadlock_detect设置为on,表示开启这个逻辑
在Innodb中,innodb_lock_wait_timeout的默认值是50s,意味着如果采用第一个策略,当出现死锁后,第一个被锁住的线程要过50s才会超时退出,然后其他线程才有可能继续执行,对于在线服务来说,这个等待时间往往是无法接受的。但是如果设置为一个很小的值,又很容易误伤。
对记录加锁时,加锁的基本单位是 next-key lock,它是由记录锁和间隙锁组合而成的,next-key lock 是前开后闭区间,而间隙锁是前开后开区间。
但是,next-key lock 在一些场景下会退化成记录锁或间隙锁
唯一索引等值查询
当我们用唯一索引进行等值查询的时候,查询的记录存不存在,加锁的规则也会不同:
当查询的记录是存在的,在用「唯一索引进行等值查询」时,next-key lock 会退化成「记录锁」。
当查询的记录是不存在的,在用「唯一索引进行等值查询」时,next-key lock 会退化成「间隙
关系型数据库和非关系型数据库区别
关系型数据库
关系型数据库代表
mysql / oracle / sql server / sqlite
什么是关系型数据库
关系型数据库最典型的数据结构是表,由二维表及其之间的联系所组成的一个数据组织。
优点:
易于维护:都是使用表结构,格式一致;
使用方便:SQL语言通用,可用于复杂查询;
复杂操作:支持SQL,可用于一个表以及多个表之间非常复杂的查询。
缺点:
读写性能比较差,尤其是海量数据的高效率读写;
固定的表结构,灵活度稍欠;
高并发读写需求,传统关系型数据库来说,硬盘I/O是一个很大的瓶颈。
非关系型数据库
非关系型数据库代表
redis / hbase / mongoDB / CouchDB / Neo4J 【注意:hive 不是数据库,是数据仓库 不是一个概念】
什么是非关系型数据库
非关系型数据库严格上不是一加粗样式种数据库,应该是一种数据结构化存储方法的集合,可以是文档或者键值对等。
优点:
- 格式灵活:存储数据的格式可以是key,value形式、文档形式、图片形式等等,文档形式、图片形式等等,使用灵活,应用场景广泛,而关系型数据库则只支持基础类型。
- 速度快:nosql可以使用硬盘或者随机存储器作为载体,而关系型数据库只能使用硬盘;
- 高扩展性;
- 成本低:nosql数据库部署简单,基本都是开源软件。
缺点:
- 不提供sql支持,学习和使用成本较高;
- 无事务处理;
- 数据结构相对复杂,复杂查询方面稍欠。
- 非关系型数据库的分类
文档型
- key-value型
- 列式数据库
- 图形数据库