MySql优化及面试

一、数据库设计

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

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

    3、并不是所有的索引对查询都有效,SQL是根据表中数据进行查询优化的,当索引列有大量数据重复时,查询可能不会去利用索引,如一表中有字段sex,male、female几乎各一半,那么即使在sex上建了索引也对查询效率起不了作用。

    4、索引不是越多越好,索引虽然可以提高相应的select的效率,但是也降低了insert和update的效率,因为inser和update时可能会重建索引。

    5、应该尽可能的避免更新索引列,因为缩影数据量的顺序就是标记录的物理存储顺序,一旦索引列改变,将会耗费很大资源。

    6、尽量使用数字型字段,若只含有数值信息的字段尽量不要涉及为字符型,因为字符型会降低查询和连接性能,增加存储开销;引擎在处理查询和连接时会逐个比较字符串中的每一个字符,而对于数字型而言只需要比较一次就够了。

    7、尽可能的使用varchar/nvarchar代替char/nchar,首先变长字段存储空间小,节约存储空间,其次对于查询来说,在一个相对较小的字段内搜索效率会高一些。

    8、尽量使用表变量来代替临时表。

    9、避免频繁创建和删除临时表,以减少系统表资源的消耗。

    10、在建立临时表时,如果一次性插入数据过大,可以使用select into代替create table,避免造成大量log,提高速度;如果数据量不大,为了缓和系统表的资源,应该先create table ,然后insert。

    11、如果使用了临时表,在存储过程的最后务必将所有的临时表显示删除,先truncate table,然后drop table,避免系统表长时间的被锁定。

二、SQL语句

    1、避免在where中使用!=或者<>操作符,否则将引擎放弃使用索引而进行全表扫描。

    2、避免在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

    3、in和not in要慎用,否则将导致全表扫描

        select id from t where num in(1,2,3)  对于连续的数值 ===> select id from t where num between 1 and 3

        不连续的数值 select id from t where num =1 union all select id from t where num =2 union all select id from t where num =3

    4、like 也会导致全表扫描

        select id from t where name like ‘%abc%’

    5、在where中使用参数也会导致全表扫描。因为SQL只有再运行时才会解析局部变量。

    6、避免在where子句中对字段进行表达式操作,会导致全表扫描。

    7、避免在where子句中对字段进行函数操作,会导致全表扫描。

    8、尽量使用exist代替in

        select num from a where num in(select num from b)===>select num from a where exist(select 1 from b where num = a.num)

    9、尽量避免使用游标

    10、避免向客户端返回大数据量

    11、进行避免大事务操作,提高并发量

    12、不要使用order by rand();

    13、使用enum而不是vachar,ENUM 类型是非常快和紧凑的。在实际上,其保存的是 TINYINT,但其外表上显示为字符串。这样一来,用这个字段来做一些选项列表变得相当的完美。如果你有一个字段,比如“性别”,“国家”,“民族”,“状态”或“部门”,你知道这些字段的取值是有限而且固定的,那么,你应该使用 ENUM 而不是 VARCHAR。

    14、把IP地址存成 UNSIGNED INT,如果使用整形存放,只需要4个字节,并且有定长的字段,在查询上会有优势。

三、面试

    数据库事务是指单个逻辑工作单元的一系列操作,可以被看作一个单元的一系列SQL语句的集合。要么全部执行,要么全部不执行。

    1、事务的特性(ACID):

    A-atomacity 原子性,事务必须是原子工作单元,对数据的修改,要么全执行,要么全不执行。

    C-consistency  一致性,事务将数据库从一种一致状态改为另外一种一致状态,在事务完成时,必须使所有的数据都保持一致。

    I-isolation 隔离性,由并发事务所做的修改必须和任何其他并发事务所做的修改隔离,事务查看数据时的状态,要么是另一并发状态发生前的状态,要么是发生后的状态。

    D-durability 持久性,事务完成,对系统的影响是永久性的。

    2、脏读,幻读,不可重复读

    脏读:事务A读取了事务B更新的且没有提交的数据,事务B回滚了事务,事务A读到的数据就是脏数据。

    不可重复读:事务A多次读取同一个数据,事务B在事务A多次读取的过程中,对数据进行了更新,导致事务A多次读取同一数据时,结果不一致。

    幻读:系统管理员A将学生成绩改为ABCDE等级,在这过程中管理员B在这个时候插入了一条有具体分数的数据,当A执行完成后还发现还有一条数据没有修改,就好像发生了幻觉一样。

    3、事务隔离级别

    读未提交:一个事务可以读取另一个事务未提交的数据。

    读已提交:一个事务要等另一个事务提交后才能读取数据。

    重复读:在事务开始读取数据时,不允许修改数据。

    序列化:是事务隔离的最高级别,在该级别下,事务串行化顺序执行,可以解决脏读、不可重复读和幻读。

    4、事务隔离是怎么实现的

    基于锁实现的。分别有行级锁(INNODB引擎),表级锁(MYISAM引擎),和页级锁(BDB引擎)。

    行级锁是Mysql中锁定力度最细的一种锁,表示只针对当前操作的行进行加锁,行级锁能大大减少数据库操作的冲突,加锁力度小,但是加锁开销最大,行级锁分为共享锁和排它锁。特点:开销大,加锁慢,会出现死锁,锁定力度最小,发生锁冲突的概率最低,并发度最高。

    表级所是Mysql中力度最大的一种锁,表示对当前操作的整张表加锁,实现简单,资源开销小,被大部分Mysql引擎支持,表级锁分为共享锁和排它锁。特点:开销小,不会出现死锁,锁力度大,发生锁冲突的概率最高,并发度低。

    页级锁是Mysql中锁力度介于行级锁和表级所中间的一种锁,表级锁速度快,但是冲突多,行级冲突少,但是速度慢,所以取了折中的页级,一定锁定相邻的一组记录。特点:开销介于行级锁和表级锁之间,会出现死锁,锁定力度介于行级锁和表级锁之间,并发度一般。

    5、死锁

    死锁是指两个或者多个事务在同一资源上相互占用,并请求锁定对方的资源,从而导致恶性循环的现象。

    常见解决死锁的办法:

        如果不同程序会并发的存取多个表,尽量约定以相同的顺序访问表,可以降低死锁几率。

        在同一个事物中,尽量一次性的锁定所需要的资源,减少死锁产生的几率。

        对非常容易产生死锁的业务,可以尝试升级锁定颗粒度,通过表级锁来减少死锁产生的概率。

        另外使用乐观锁也是一种办法。

    6、SQL生命周期

     应用服务器和数据库服务器简历一个连接

     数据库进程拿到请求sql

     解析并生成执行计划,执行

     读取数据到内存并进行逻辑处理

     通过已建立的连接,将结果发送给客户端

     关掉连接,释放资源

   7、关键字执行顺序

     FROM->ON->OUTER(JOIN)->WHERE->GROUP BY->CUTE|ROLL UP->HAVING->SELECT->DISTINCT->ORDER BY->TOP

    8、乐观锁、悲观锁及其实现方式

        悲观锁:指对数据被银外修改保持保守态度,依赖数据库原生支持的锁机制来保证当前事务处理的安全性,防止其他并发实物对目标数据破坏或者破坏其他并发事务数据,将在事务开始执行前或者执行中申请锁定,执行完成后再释放锁。对长事务来说,可能会严重影响到系统的并发处理能力。自带的数据库事务就是悲观锁。

        乐观锁:每次拿数据的时候都认为其他事务不会修改,所以不会上锁,但是在提交更新的时候会判断一下在此期间别人有没有去更新这个数据。乐观锁适用于读多写少的应用场景,可以提高吞吐量。一般是加一个版本号,每次更新比较这个版本号。

    9、数据库连接池

        数据库更适合长连接,所以连接池可以对连接复用,维护、分配、管理、释放连接对象,也可以避免创建大量的连接对象而对数据库引发各种问题,通过请求排队,也可以缓解对数据库的冲击。

    10、char和varchar的区别

    char是定长的,每个数据都会是相同的长度,varchar是变长的,只有一个最大的长度,能有效的节约空间,提高性能。

    11、TRUNCATE和DELETE的却别

    DELETE是删除一行,可以回滚;TRUNCATE是永久性的删除每一行,不能回滚。

    12、触发器

    触发器是指一段代码,当触发某个事件时,自动执行这些代码,Mysql中有 Befor Insert,After Insert,Befor Update,After Update,Befor Delete,After Delete;

    13、FLOAT和DOUBLE的区别

    FLOAT 类型数据可以存储至多8位十进制数,占4字节,DOUBLE之多可以存储18位十进制数,占8个字节。

    14、获取日期

        SELECT CURRENT_DATE();

    15、int(0),char(16),varchar(16),datetime, text数据类型的意义

     int(0)表示数据是INT类型,长度是0;char(16)表示固定长度字符串,长度是16,;varchar(16)表示变长字符串,最大长度是16;datetime表示时间类型;text表示字符串类型,能存储大字符串,最多存储65535字节数据。

    16、InnoDB和MyISAM区别

    InnoDB支持事务,MyISAM不支持;

    InnoDB数据存在共享表空间,MyISAM数据存储在文件中;

    InnoDB支持行级锁,MyISAM只支持表级锁;

    InnoDB崩溃后恢复,MyISAM不支持;

    InnoDB支持外键,MyISAM不支持;

    InnoDB支持全文索引,MyISAM支持全文索引;

    17、InnoDB引擎的特性

    插入缓冲(insert buffer),二次写(double write),自适应哈希索引(ahi),预读(read head)

    18、Mysql的引擎

    InnoDB,MyISAM,Memory

    19、varchar和text的区别

    varchar可以指定长度,text不可以指定长度;text类型不能有默认值;varchar可以创建缩索引,text创建索引需要指定多少个字符,varchar查询速度快于text,在都有索引的情况下,text的索引基本没有用;查询text需要创建临时表;

    20、varchar(50)中50的含义

    最多存放50个字符,varchar(50)和varchar(200)存储的空间一样,但是后者在拍讯上会消耗更多内存。

    21、MyISAM索引的实现

    MyISAM存储引擎使用B+Tree作为索引结构

    22、InnoDB存储引擎

    InnoDB给MySQL的表提供了事务处理、回滚、崩溃修复能力和多版本并发控制的事务安全。它是MySQL上第一个提供外键约束的表引擎,现在MySQL的默认引擎是InnoDB。

    InnoDB存储引擎总支持AUTO_INCREMENT。自动增长列的值不能为空,而且值必须唯一。MySQL规定自增长列必须为主键。在插入值的时候,如果自动增长列不输入值,则插入的值为自动增长后的值;如果输入的值为0或空(NULL),则插入的值也是自动增长后的值;如果插入某个确定的值,且该值在前面没有出现过,就可以直接插入。

    InnoDB还支持外键,我见所在的表叫做字表,外键所依赖的表叫做父表。父表中被子表外键关联的字段必须为主键。

    InnoDB中,创建的表的表结构存储在.fml文件中。数据和索引存储在innodb_db_home_dir和innodb_data_file_path定义的表空间中。

    InnoDB的优势在于提供了良好的事务处理、崩溃修复能力和并发控制。缺点是读写效率较差,占用的数据空间相对较大。

    23、MyISAM存储引擎

    MyISAM的表存储成3个文件。文件的名字与表名相同。扩展名为frm、MYD、MYI。其实,frm文件存储表的结构,MYD文件存储数据,MYI文件存储索引。

    基于MyISAM存储引擎的表支持3中不同的存储格式。包括静态型、动态型和压缩型,静态型是MyISAM的默认存储格式。它的字段是固定长度的;动态型包含变长字段,记录的长度不是固定的;压缩型需要用到myisampack工具,占用的磁盘空间较小。

    MyISAM的优势在于占用空间小,处理速度快。缺点是不支持事务的完整性和并发性。

    24、MEMORY存储引擎

    MEMORY是一类特殊的存储引擎,使用存储在内存中的内容来创建表,而且数据全部放在内存中。

    每个基于MEMORY存储引擎的表实际对应一个磁盘文件。该文件的文件名和表名相同,类型为.frm类型。改文件中只存储表的结构,其数据文件都存在内存中,这样有利于数据的快速处理,提高整个表的效率。所以服务器需要有足够的内存来维持MEMORY存储引擎的表的使用,如果不需要了,可以释放内存,甚至删除不需要的表。

    MEMORY默认使用哈希索引。速度比使用B型树索引快。

    25、三种引擎的比较


    InnoDB:支持事务处理,支持外键,支持崩溃修复能力和并发控制。如果需要对事务的完整性要求比较高(比如银行),要求实现并发控制(比如售票),那选择InnoDB有很大的优势。如果需要频繁的更新、删除操作的数据库,也可以选择InnoDB,因为支持事务的提交(commit)和回滚(rollback)。 

    MyISAM:插入数据快,空间和内存使用比较低。如果表主要是用于插入新记录和读出记录,那么选择MyISAM能实现处理高效率。如果应用的完整性、并发性要求比 较低,也可以使用。

    MEMORY:所有的数据都在内存中,数据的处理速度快,但是安全性不高。如果需要很快的读写速度,对数据的安全性要求较低,可以选择MEMOEY。它对表的大小有要求,不能建立太大的表。所以,这类数据库只使用在相对较小的数据库表。

注意,同一个数据库也可以使用多种存储引擎的表。如果一个表要求比较高的事务处理,可以选择InnoDB。这个数据库中可以将查询要求比较高的表选择MyISAM存储。如果该数据库需要一个用于查询的临时表,可以选择MEMORY存储引擎。

你可能感兴趣的:(MySql优化及面试)