数据库——mysql

1、分库分表的依据

--> 按大数据字段分、按时间段分、按具体业务分(如企业,地区,年龄段等)

又有范围法和哈希法

2、分表后怎么保证主键位唯一

--> 要求:

1.全局唯一性,不能出现重复的id号,

2.信息安全:防止恶意用户规矩id的规则来获取数据

3.数据递增:保证我的下一ID一定大于上一个ID

有几种策略:UUID 、雪花算法snowflake(twitter公司,高位随机+毫秒数+机器码(数据中心+机器id)+10的流水号)、mysql、redis 

3、sql语句从提交到执行的过程

第一步:客户端把语句发给服务器端执行

第二步:语句解析

查询高速缓存(library cache)

语句合法性检查(data dict cache)

语言含义检查(data dict cache)

获得对象解析锁(control structer)

数据访问权限的核对(data dict cache)

确定最佳执行计划

第三步:绑定变量赋值

第四步:语句执行

第五步:提取数据

4、什么情况下会导致索引失效

  1. 如果条件中有or,即使其中有条件带索引也不会使用(这也是为什么尽量少用or的原因)

注意:要想使用or,又想让索引生效,只能将or条件中的每个列都加上索引

2.like查询是以%开头

3.如果列类型是字符串,那一定要在条件中将数据使用引号引用起来,否则不使用索引

4.如果mysql估计使用全表扫描要比使用索引快,则不使用索引

 where语句中对字段表达式操作

 where语句中使用Not In

where语句中使用 <> !=

5、#和$的区别

两者均为mysql动态sql的语法,但两者在预编译时的处理不一样

#在sql中使用的是占位符,而$则直接使用字符串进行填充,存在sql注入的风险

#{} 的参数替换是发生在 DBMS 中,而 ${} 则发生在动态解析过程中。

表名用参数传递进来的时候,只能使用 ${}

6、statement和preparedStatement的区别,怎么编译的

关系:PreparedStatement继承自Statement,都是接口
区别:PreparedStatement可以使用占位符,是预编译的,批处理比Statement效率高    

PreparedStatement语句第二次执行时,存在高速缓存,省去了语句合法性、语句含义、获取对象锁及权限核对检查、确定最佳执行计划等,提高了效率。同时可以防止sql注入攻击。

1、PreparedStatement:表示预编译的 SQL 语句的对象。

   接口:public interface PreparedStatement extends Statement之间的继承关系

   SQL 语句被预编译并存储在 PreparedStatement 对象中。然后可以使用此对象多次高效地执行该语句。

2、Statement:用于执行静态 SQL 语句并返回它所生成结果的对象。

   接口:public interface Statement extends Wrapper

在默认情况下,同一时间每个 Statement 对象只能打开一个 ResultSet 对象。因此,如果读取一个 ResultSet 对象与另一个交叉,则这两个对象必须是由不同的 Statement 对象生成的。如果存在某个语句的打开的当前 ResultSet 对象,则 Statement 接口中的所有执行方法都会隐式关闭它。  

7、mysql的默认隔离级别,能解决什么问题,不能解决什么问题

数据库事务的隔离级别有4个,由低到高依次为Read uncommitted(读未提交)、Read committed(读提交)、Repeatable rea(重复读)、Serializable(序列化),这四个级别可以逐个解决脏读、不可重复读、幻读这几类问题。

√: 可能出现    ×: 不会出现

 

脏读

不可重复读

幻读

Read uncommitted

Read committed--Sql Server , Oracle

×

Repeatable read--MySQL

×

×

Serializable

×

×

×

 

为什么说反序列化可以解决幻读?

 

8、mysql的两种日志级别,分别是做什么用的

Undo日志和Redo日志

Undo日志:用于存放数据被修改前的值,如果这个修改出现异常,可以使用undo日志实现回滚操作,保证事务一致性

Redo日志:用于记录数据修改后的数据,顺序记录。当buffer pool 中的数据还没刷新到磁盘的时候发生crash时,可以通过redo log找到需要重新刷新到磁盘文件的记录;将buffer pool 中数据记录到redo log,是一个顺序IO,可以提高事务提交的速度。 

9、mysql的主键为什么要用自增主键

InnoDB引擎表的特点

1InnoDB引擎表是基于B+树的索引组织表(IOT)

关于B+

https://images2015.cnblogs.com/blog/268981/201510/268981-20151009211335362-543150641.jpg

B+ 树的特点:

1)所有关键字都出现在叶子结点的链表中(稠密索引),且链表中的关键字恰好是有序的;

2)不可能在非叶子结点命中;

3)非叶子结点相当于是叶子结点的索引(稀疏索引),叶子结点相当于是存储(关键字)数据的数据层;

 

2、如果我们定义了主键(PRIMARY KEY),那么InnoDB会选择主键作为聚集索引、如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引、如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增,这个ROWID不像ORACLEROWID那样可引用,是隐含的)

3、数据记录本身被存于主索引(一颗B+Tree)的叶子节点上。这就要求同一个叶子节点内(大小为一个内存页或磁盘页)的各条数据记录按主键顺序存放,因此每当有一条新的记录插入时,MySQL会根据其主键将其插入适当的节点和位置,如果页面达到装载因子(InnoDB默认为15/16),则开辟一个新的页(节点)

4、如果表使用自增主键,那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,当一页写满,就会自动开辟一个新的页

5、如果使用非自增主键(如果身份证号或学号等),由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

 

综上总结,如果InnoDB表的数据写入顺序能和B+树索引的叶子节点顺序一致的话,这时候存取效率是最高的,也就是下面这几种情况的存取效率最高:

1、使用自增列(INT/BIGINT类型)做主键,这时候写入顺序是自增的,和B+数叶子节点分裂顺序一致;

2、该表不指定自增列做主键,同时也没有可以被选为主键的唯一索引(上面的条件),这时候InnoDB会选择内置的ROWID作为主键,写入顺序和ROWID增长顺序一致;
除此以外,如果一个InnoDB表又没有显示主键,又有可以被选择为主键的唯一索引,但该唯一索引可能不是递增关系时(例如字符串、UUID、多字段联合唯一索引的情况),该表的存取效率就会比较差。

 

10、项目中使用的发号器生成主键的算法是什么

--> 位运算、或运算

雪花算法snowflake(twitter公司,高位随机+毫秒数+机器码(数据中心+机器id)+10的流水号)

11、共享锁与排他锁

共享锁【S锁】

又称读锁,若事务T对数据对象A加上S锁,则事务T可以读A但不能修改A,其他事务只能再对A加S锁,而不能加X锁,直到T释放A上的S锁。

 

这保证了其他事务可以读A,但在T释放A上的S锁之前不能对A做任何修改。

 

排他锁【X锁】

又称写锁。若事务T对数据对象A加上X锁,事务T可以读A也可以修改A,其他事务不能再对A加任何锁,直到T释放A上的锁。

 

这保证了其他事务在T释放A上的锁之前不能再读取和修改A。

 

12、数据库的MVCC

Multi-Version Concurrency Control 多版本并发控制

1.MVCC(多版本并发控制),是一种不利用锁机制实现的隔离级别,主要实现了在保证数据的一致性的前提下,实现了读写的并行。

  之前提到的读已提交,虽然实现了读写并行,读未提交实现了写读并行,读写并行;但是两种隔离级别均没有保证数据的一致性,分别出现不可重复读和脏读。

  2.mvcc的原理是给每一数据的更新都有一个版本号。当写事务正在进行时,此时过来一个读事务,读事务会首先生成一个版本号,即该事物想读取哪一个版本的数据。

   然后,写事务更新数据,读事务读取之前相应版本的数据,而保证了不出现不可重复读和脏读的情况。

  3.之前提到,保证数据一致性有两种方式,要么将读事务读取视点1的数据,要么读取视点2的数据。在mvcc中保证数据一致性的方法选择的是,读取视点1的数据,即读取的          是写事务开始之前的旧版本数据。

https://images2015.cnblogs.com/blog/801049/201608/801049-20160818103001843-339122414.png

 

13、Sql中Exist和in的区别

结论:in()适合B表比A表数据小的情况

结论:exists()适合B表比A表数据大的情况

A表数据与B表数据一样大时,inexists效率差不多,可任选一个使用.

区别及应用场景

    in exists的区别: 如果子查询得出的结果集记录较少,主查询中的表较大且又有索引时应该用in, 反之如果外层的主查询记录较少,子查询中的表大,又有索引时使用exists。其实我们区分inexists主要是造成了驱动顺序的改变(这是性能变化的关键),如果是exists,那么以外层表为驱动表,先被访问,如果是IN,那么先执行子查询,所以我们会以驱动表的快速返回为目标,那么就会考虑到索引及结果集的关系了 ,另外IN时不对NULL进行处理。

    in 是把外表和内表作hash 连接,而exists是对外表作loop循环,每次loop循环再对内表进行查询。一直以来认为existsin效率高的说法是不准确的。

 

not in 和not exists:

    如果查询语句使用了not in 那么内外表都进行全表扫描,没有用到索引;而not extsts 的子查询依然能用到表上的索引。所以无论那个表大,用not exists都比not in要快

 

14、Mysql的存储引擎及其之间的区别

MyISAM

  1. 不支持事务,但是每次查询都是原子的;
  2. 支持表级锁,即每次操作是对整个表加锁;
  3. 存储表的总行数;
  4. 一个MYISAM表有三个文件:索引文件、表结构文件、数据文件;
  5. 采用非聚集索引,索引文件的数据域存储指向数据文件的指针。辅索引与主索引基本一致,但是辅索引不用保证唯一性。

InnoDb

  1. 支持ACID的事务,支持事务的四种隔离级别;
  2. 支持行级锁及外键约束:因此可以支持写并发;
  3. 不存储总行数;
  4. 一个InnoDb引擎存储在一个文件空间(共享表空间,表大小不受操作系统控制,一个表可能分布在多个文件里),也有可能为多个(设置为独立表空,表大小受操作系统文件大小限制,一般为2G),受操作系统文件大小的限制;
  5. 主键索引采用聚集索引(索引的数据域存储数据文件本身),辅索引的数据域存储主键的值;因此从辅索引查找数据,需要先通过辅索引找到主键值,再访问辅索引;最好使用自增主键,防止插入数据时,为维持B+树结构,文件的大调整。

15、存储过程与函数的区别?

 

16、数据库优化法则

1、减少数据访问

创建并使用正确的索引

只通过索引访问数据

2、返回更少数据

3、减少交互次数

4、减少数据库服务器CPU运算

5、利用更多的资源

17、怎么确定哪些语句需要优化,进行定位

比如100条查询语句

mysql:

a、explain+sql语句

b、show profiles

c、show status

oracle:

a、oracle可以使用autotrace跟踪sql语句

或者选择解释计划查看sql语句的执行计划

b、sql调优顾问STA

c、实时sql监视  在oracle的企业管理工具中

 

18、索引分类及对索引的理解

索引结构上主要分为聚簇索引和非聚簇索引

索引按数据库功能分类:普通索引、唯一索引、主键索引、组合索引

 

19B树索引和B+树索引的区别

 

20、组合索引的顺序有区别吗?如A字段+B字段和B字段+A字段

联合索引也是个不错的方案,ab,还是ba,则同上,区分度高者,在前。

联合索引的问题?

where a = “xxx” 可以使用 AB 联合索引
where b = “xxx” 则不可 (再想象一下,这是书的目录?)

所以,大多数情况下,有AB索引了,就可以不用在去建一个A索引了

 

联合索引又叫复合索引。对于复合索引:Mysql从左到右的使用索引中的字段,一个查询可以只使用索引中的一部份,但只能是最左侧部分。例如索引是key index (a,b,c). 可以支持a | a,b| a,b,c 3种组合进行查找,但不支持 b,c进行查找 .当最左侧字段是常量引用时,索引就十分有效。

 

联合索引IDX(字段A,字段B,字段C,字段D),当仅使用字段A查询时,索引IDX就会使用到;

如果仅使用字段B或字段C或字段D查询,则索引IDX都不会用到。  

 

mysql创建复合索引的规则是首先会对复合索引的最左边的,也就是第一个name字段的数据进行排序,在第一个字段的排序基础上,然后再对后面第二个的cid字段进行排序。其实就相当于实现了类似 order by name cid这样一种排序规则。

所以:第一个name字段是绝对有序的,而第二字段就是无序的了。所以通常情况下,直接使用第二个cid字段进行条件判断是用不到索引的,当然,可能会出现上面的使用index类型的索引。这就是所谓的mysql为什么要强调最左前缀原则的原因。

21、mysql与oracle的区别

1. Oracle是大型数据库而Mysql是中小型数据库,Oracle市场占有率达40%,Mysql只有20%左右,同时Mysql是开源的而Oracle价格非常高。数据量和复杂连表查询支持上存在很大的区别

2. Oracle支持大并发,大访问量,是OLTP最好的工具。

3. 安装所用的空间差别也是很大的,Mysql安装完后才152M而Oracle有3G左右,且使用的时候Oracle占用特别大的内存空间和其他机器性能。

4.Oracle和Mysql操作上的区别

①主键

Mysql一般使用自动增长类型,在创建表时只要指定表的主键为auto increment,插入记录时,不需要再指定该记录的主键值,Mysql将自动增长;Oracle没有自动增长类型,主 
键一般使用的序列,插入记录时将序列号的下一个值付给该字段即可;只是ORM框架是只要是native主键生成策略即可。

②单引号的处理

MYSQL里可以用双引号包起字符串,ORACLE里只可以用单引号包起字符串。在插入和修改字符串前必须做单引号的替换:把所有出现的一个单引号替换成两个单引号。

③翻页的SQL语句的处理

MYSQL处理翻页的SQL语句比较简单,用LIMIT 开始位置, 记录个数;ORACLE处理翻页的SQL语句就比较繁琐了。每个结果集只有一个ROWNUM字段标明它的位置, 并且只能用 
ROWNUM<100, 不能用ROWNUM>80

④ 长字符串的处理

长字符串的处理ORACLE也有它特殊的地方。INSERT和UPDATE时最大可操作的字符串长度小于等于4000个单字节, 如果要插入更长的字符串, 请考虑字段用CLOB类型,方法借用 
ORACLE里自带的DBMS_LOB程序包。插入修改记录前一定要做进行非空和长度判断,不能为空的字段值和超出长度字段值都应该提出警告,返回上次操作。

⑤空字符的处理

MYSQL的非空字段也有空的内容,ORACLE里定义了非空字段就不容许有空的内容。按MYSQL的NOT NULL来定义ORACLE表结构, 导数据的时候会产生错误。因此导数据时要对空字符 
进行判断,如果为NULL或空字符,需要把它改成一个空格的字符串。

⑥字符串的模糊比较

MYSQL里用 字段名 like '%字符串%',ORACLE里也可以用 字段名 like '%字符串%' 但这种方法不能使用索引, 速度不快。

⑦Oracle实现了ANSII SQL中大部分功能,如,事务的隔离级别、传播特性等而Mysql在这方面还是比较的弱。

 

22、多对多情况下该怎么建表?最佳方案?

增加中间表,设置联合主键

联合主键:多个主键联合形成一个主键的组合。

当两个数据表是多对多的关系,需要通过两个数据表的主键来组成联合主键,来确定一条记录

复合主键:数据库表的主键由两个及以上的字段组成。

22、建立索引的原则

实际中的一些通用的原则: 

1. 在经常用作过滤器的字段上建立索引; 

2. SQL语句中经常进行GROUP BYORDER BY的字段上建立索引; 

3. 在不同值较少的字段上不必要建立索引,如性别字段; 

4. 对于经常存取的列避免建立索引; 

5. 用于联接的列(主健/外健)上建立索引; 

6. 在经常存取的多个列上建立复合索引,但要注意复合索引的建立顺序要按照使用的频度来确定; 

7. 缺省情况下建立的是非簇集索引,但在以下情况下最好考虑簇集索引,如:含有有限数目(不是很少)唯一的列;进行大范围的查询;充分的利用索引可以减少表扫描I/0的次数,有效的避免对整表的搜索。当然合理的索引要建立在对各种查询的分析和预测中,也取决于DBA的所设计的数据库结构。

8. 避免选择大型数据类型的列作为索引。

23、主键和唯一索引的区别

主键是一种约束,唯一索引是一种索引,两者在本质上是不同的。

主键创建后一定包含一个唯一性索引,唯一性索引并不一定就是主键。

唯一性索引列允许空值,而主键列不允许为空值。

主键列在创建时,已经默认为空值 + 唯一索引了。

主键可以被其他表引用为外键,而唯一索引不能。

一个表最多只能创建一个主键,但可以创建多个唯一索引。

主键更适合那些不容易更改的唯一标识,如自动递增列、身份证号等。

RBO 模式下,主键的执行计划优先级要高于唯一索引。 两者可以提高查询的速度。

 

24、MyCat—数据库中间件

一、什么是MyCat:

MyCat是一个开源的分布式数据库系统,是一个实现了MySQL协议的服务器,前端用户可以把它看作是一个数据库代理,用MySQL客户端工具和命令行访问,而其后端可以用MySQL原生协议与多个MySQL服务器通信,也可以用JDBC协议与大多数主流数据库服务器通信,其核心功能是分表分库,即将一个大表水平分割为N个小表,存储在后端MySQL服务器里或者其他数据库里。

 

MyCat发展到目前的版本,已经不是一个单纯的MySQL代理了,它的后端可以支持MySQL、SQL Server、Oracle、DB2、PostgreSQL等主流数据库,也支持MongoDB这种新型NoSQL方式的存储,未来还会支持更多类型的存储。而在最终用户看来,无论是那种存储方式,在MyCat里,都是一个传统的数据库表,支持标准的SQL语句进行数据的操作,这样一来,对前端业务系统来说,可以大幅降低开发难度,提升开发速度

 

二、那么为什么要用到MyCat呢?

例如操作系统是对各类计算机硬件的抽象。那么我们什么时候需要抽象?假如只有一种硬件的时候,我们需要开发一个操作系统吗?

再比如一个项目只需要一个人完成的时候不需要leader,但是当需要几十人完成时,就应该有一个管理者,发挥沟通协调等作用,而这个管理者对于他的上层来说就是对项目组的抽象。

同样的,当我们的应用只需要一台数据库服务器的时候我们并不需要Mycat,而如果你需要分库甚至分表,这时候应用要面对很多个数据库的时候,这个时候就需要对数据库层做一个抽象,来管理这些数据库,而最上面的应用只需要面对一个数据库层的抽象或者说数据库中间件就好了,这就是Mycat的核心作用。

所以可以这样理解:数据库是对底层存储文件的抽象,而Mycat是对数据库的抽象。

 

 

猜你喜欢

转载自blog.csdn.net/qq_39159227/article/details/89036025