美文网首页MySQL
数据库面试题

数据库面试题

作者: printf200 | 来源:发表于2019-06-18 01:27 被阅读42次

    1.MYSQL的复制原理以及流程。

    基本原理流程,3个线程以及之间的关系

    主:binlog线程---记录下所有改变数据库数据的语句,放进master上的binlog中
    /*
    mysql-binlog是MySQL数据库的二进制日志,用于记录用户对数据库操作的SQL语句((除了数据查询语句)信息。可以使用mysqlbin命令查看二进制日志的内容。
    */
    从:io线程---在使用start slave之后,负责从master上拉取binlong内容,放进自己的relaylog中
    从:sql执行线程---执行relay log中的语句。

    2.MySQL中myisam与innodb的区别

    (1)5点不同

    1.innodb支持事务,myisam不支持事务
    /*
    MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你即需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!
    事务是必须满足4个条件(ACID)::原子性(Atomicity,或称不可分割性)、一致性(Consistency)、隔离性(Isolation,又称独立性)、持久性(Durability)。
    */
    2.innodb支持行级锁,myisam支持表级锁
    3.innodb支持MVCC,myisam不支持
    4.innodb支持外键,而myisam不支持
    5.innodb不支持全文索引,myisam支持

    (2)innodb引擎的四大特性

    ①插入缓冲(insert buffer)
    ②二次写(double write)
    ③自适应哈希索引(ahi)
    ④预读(read ahead)

    (3)2者selectcount(*)哪个更快,为什么

    myisam更快,因为myisam内部维护了一个计数器,可以直接调取。

    3.MySQL中的varchar与char的区别以及varchar(50)中的50代表的含义。

    (1)varchar与char的区别
    char是一种固定长度的类型,varchar则是一种可变长度的类型。
    (2)varchar(50)中50的含义
    最多存放50个字符,varchar(50)和(200)存储hello所占的空间一样,但后者在排序时会消耗更多内存,因为order by col 采用fixed_lenght计算col长度(memory引擎也一样)
    (3)int(20)中20的涵义
    是指显示字符的长度
    但是加参数的,最大为255,比如它是记录行数的id,插入10条,它就显示00000000001 ~~~00000000010,当字符的位数超过11,它也只显示11位,如果你没有加那个让它未满11位就前面加0的参数,它不会在前面加0
    20表示最大显示宽度为20,但仍占4字节存储,存储范围不变。

    4.innodb的事务与日志的实现方式

    1.有多少种日志:
    错误日志、查询日志、慢查询日志、二进制日志、中继日志、事务日志
    2.事务的4钟隔离级别
    读未提交(RU)
    读已提交(RC)
    可重复读(RR)
    串行
    3.事务是如何通过日志来实现的?
    事务日志是通过redo和innodb的存储引擎日志(Innodb log buffer)缓冲来实现的,当开始一个事务的时候,会记录事务的lsn(log sequence number)号,当事务执行时,会往innodb存储引擎的日志的日志缓存里面插入事务日志,当事务提交时,必须将存储引擎的日志缓冲写入磁盘(通入innodb_flush_log_at_trx_commit来控制),也就是写数据前,需要先写日志。这种方式成为“预写日志方式”。

    5.MySQL binlong的几种日志录入格式以及区别

    1.binlog的日志格式的种类和分别
    2.适用场景
    3.结合第一个问题,每一种日志格式在复制中的优劣
    Statement:每一条会修改数据的sql都会记录在binlog中。
    优点:不需要记录每一行的变化,减少了binlog日志量,节约了IO,提高性能。(相比row能节约多少性能 与日志量,这个取决于应用的SQL情况,正常同一条记录修改或者插入row格式所产生的日志量还小于Statement产生的日志量,但是考虑到如果带条 件的update操作,以及整表删除,alter表等操作,ROW格式会产生大量日志,因此在考虑是否使用ROW格式日志时应该跟据应用的实际情况,其所 产生的日志量会增加多少,以及带来的IO性能问题。)
    缺点:由于记录的只是执行语句,为了这些语句能在slave上正确运行,因此还必须记录每条语句在执行的时候的 一些相关信息,以保证所有语句能在slave得到和在master端执行时候相同 的结果。另外mysql 的复制,像一些特定函数功能,slave可与master上要保持一致会有很多相关问题(如sleep()函数, last_insert_id(),以及user-defined functions(udf)会出现问题).
    使用以下函数的语句也无法被复制:

    • LOAD_FILE()
    • UUID()
    • USER()
    • FOUND_ROWS()
    • SYSDATE() (除非启动时启用了 --sysdate-is-now 选项)
      同时在INSERT ...SELECT 会产生比 RBR 更多的行级锁
      2.Row:不记录sql语句上下文相关信息,仅保存哪条记录被修改。
      优点: binlog中可以不记录执行的sql语句的上下文相关的信息,仅需要记录那一条记录被修改成什么了。所以rowlevel的日志内容会非常清楚的记录下 每一行数据修改的细节。而且不会出现某些特定情况下的存储过程,或function,以及trigger的调用和触发无法被正确复制的问题
      缺点:所有的执行的语句当记录到日志中的时候,都将以每行记录的修改来记录,这样可能会产生大量的日志内容,比 如一条update语句,修改多条记录,则binlog中每一条修改都会有记录,这样造成binlog日志量会很大,特别是当执行alter table之类的语句的时候,由于表结构修改,每条记录都发生改变,那么该表每一条记录都会记录到日志中。
      3.Mixedlevel: 是以上两种level的混合使用,一般的语句修改使用statment格式保存binlog,如一些函数,statement无法完成主从复制的操作,则 采用row格式保存binlog,MySQL会根据执行的每一条具体的sql语句来区分对待记录的日志形式,也就是在Statement和Row之间选择 一种.新版本的MySQL中队row level模式也被做了优化,并不是所有的修改都会以row level来记录,像遇到表结构变更的时候就会以statement模式来记录。至于update或者delete等修改数据的语句,还是会记录所有行的 变更。

    6.SQL的优化

    1.在表中建立索引,优先考虑where.group by使用到的字段。
    2.查询条件中,一定不要使用select ,因为会返回过多无用的字段会降低查询效率。应该使用具体的字段代替,只返回使用到的字段。
    3.不要在where条件中使用左右两边都是%的like模糊查询,如:
    SELECT * FROM t_order WHERE customer LIKE '%zhang%'
    这样会导致数据库引擎放弃索引进行全表扫描。
    优化:尽量在字段后面使用模糊查询。如下:
    SELECT * FROM t_order WHERE customer LIKE 'zhang%'
    4.尽量不要使用in 和not in,会造成全表扫描。如下:
    SELECT * FROM t_order WHERE id IN (2,3)
    SELECT * FROM t_order1 WHERE customer IN (SELECT customer FROM t_order2)
    优化:
    对于连续的数值,能用 between 就不要用 in ,如下:
    SELECT * FROM t_order WHERE id BETWEEN 2 AND 3
    对于子查询,可以用exists代替。如下:
    SELECT * FROM t_order1 WHERE EXISTS (SELECT * FROM t_order2 WHERE t1.customer = t2.customer)
    5.尽量不要使用or,会造成全表扫描。如下:
    SELECT * FROM t_order WHERE id = 1 OR id = 3
    优化:可以用union代替or。如下:
    SELECT * FROM t_order WHERE id = 1
    UNION
    SELECT * FROM t_order WHERE id = 3
    6.尽量不要在 where 子句中对字段进行表达式操作,这样也会造成全表扫描。如:
    select id FROM t_order where num/2=100
    应改为:
    select id FROM t_order where num=1002
    7.where条件里尽量不要进行null值的判断,null的判断也会造成全表扫描。如下:
    SELECT * FROM t_order WHERE score IS NULL
    优化:
    给字段添加默认值,对默认值进行判断。如:
    SELECT * FROM t_order WHERE score = 0
    8.尽量不要在where条件中等号的左侧进行表达式.函数操作,会导致全表扫描。如下:
    SELECT * FROM t_order2 WHERE score/10 = 10
    SELECT * FROM t_order2 WHERE SUBSTR(customer,1,5) = 'zhang'
    优化:
    将表达式.函数操作移动到等号右侧。如下:
    SELECT * FROM t_order2 WHERE score = 10
    10
    SELECT * FROM t_order2 WHERE customer LIKE 'zhang%'
    9.尽量不要使用where 1=1的条件
    有时候,在开发过程中,为了方便拼装查询条件,我们会加上该条件,这样,会造成>进行全表扫描。如下:
    SELECT * FROM t_order WHERE 1=1
    优化:
    如果用代码拼装sql,则由代码进行判断,没where加where,有where加and
    如果用mybatis,请用mybatis的where语法。
    10.程序要尽量避免大事务操作,提高系统并发能力。
    11.一个表的索引数最好不要超过6个,如果索引太多的话,就需要考虑一下那些不常使用到的列上建的索引是否有必要。

    相关文章

      网友评论

        本文标题:数据库面试题

        本文链接:https://www.haomeiwen.com/subject/pugtqctx.html