mysql

三大范式

:(1)每个列不可拆分;(2)完全依赖主键,不能只依赖一部分;(3)只依赖主键,不依赖其他非主键。

日志:

binlog记录了mysql对数据库执行更改的所有操作,可以用来做数据归档和数据恢复。
(1)undolog(回滚日志):保存了事务发生之前的数据的一个版本,可以用于回滚,同时可提供多版本并发控制下的读(MVCC)。逻辑格式。
(2)binlog(mysql-bin.000001):用于复制。逻辑格式。三种录入格式:1)statement(默认),基于SQL语句来记录;2)row,记录每一行的改动,日志太多且耗费大量IO资源;3)mixed,折中方式,默认采用statement,但是一旦它判断可能会有数据不一致的情况发生,就会采用row格式记录。
事务提交的时候,一次性将事务中的sql语句按照一定的格式记录到binlog中。根据配置参数保存的天数释放的。
(3)redolog:(ib_logfile0/ib_logfile1)重做日志,确保事务的持久性。防止系统发生故障时,仍有数据未写入磁盘,重启后可以根据redolog重做。物理格式。事务开始之后就产生redolog,边执行边写入redolog(并不是提交时才写)。写入磁盘之后就可以释放。
(4)错误日志
(5)慢查询日志
(6)中继日志

引擎:

存储引擎是基于表的,而不是基于库的。mysql 默认存储引擎为InnoDB
InnoDB:支持事务,行锁(适合高并发)和表锁,支持外键。
MyISAM:不支持事务,表锁,不支持外键。
MEMORY:不支持事务,表锁:数据都在内存中,处理速度快,但安全性不高。

表锁(意向锁,自增锁)和行锁(共享锁,排他锁)的区别:
锁定粒度:表锁>行锁
加锁效率:表锁>行锁
冲突概率:表锁>行锁
并发性能:表锁<行锁
MyISAM和InnoDB区别
(1)存储结构:InnoDB表数据和索引保存在一个文件中,MyISAM表结构和索引保存在不同文件中。
(2)MyISAM:不支持事务,行级锁和外键。InnoDB:支持事务,行级锁,外键。
(3)select count(*) MyISAM内部存储了所有行的值,更快。InnoDB需要扫描全表
(4)MyISAM支持全文索引,InnoDB不支持。
(5)MyISAM不支持哈希索引,InnoDB支持。
(6)MyISAM索引和InnoDB都是采用B+Tree作为索引结构,但MyISAM是非聚簇索引,叶节点的data域存放的是数据记录的地址,主索引和辅助索引在结构上没有任何区别,只是主索引要求key唯一,辅助索引的key可以重复;InnoDB是聚簇索引,主索引的叶节点data域保存了完整的数据记录,而辅助索引data域记录主键的值。

MyISAM查询效率比InnoDB高也是由于此:MyISAM索引和数据分离,索引很小,可以一次性将索引加载至内存中,IO少,而InnoDB索引和数据在一起,必须采用多次IO读取节点。

非聚簇索引和聚簇索引:
非聚簇索引,叶节点的dta域存放的是数据记录的地址,不一定要回表,如果索引覆盖查询,不用回表查询。select age from employee where age < 20,全部命中了索引。
聚簇索引:主索引叶节点的dta域保存了完整的数据记录,副主索引的data域记录主键的值。

B Tree和 B+ Tree:
BTree的所有节点都会存储行数据,查询效率不稳定
B+ Tree非叶子节点只存储主键,叶子节点存放数据,且是有序链表,便于范围查询。

索引:

定义:提高查询效率的一种数据结构、文件。
优点:(1)提高查询速度;(2)提高排序速度;(3)提高分组速度
缺点:(1)创建、维护索引都需要耗费时间,降低了增删改的效率;(2)太多索引会增加查询优化器的选择时间

索引使用场景:
(1)where;(2)order by;(3)join;(4)索引覆盖:尽可能的在select后只写必要的查询字段,以增加索引覆盖的几率。

类型:
(1)主键索引;
(2)唯一索引 ALTER TABLE table_name ADD UNIQUE (column);
(3)普通索引 ALTER TABLE table_name ADD INDEX index_name (column);
(4)全文索引 ALTER TABLE table_name ADD FULLTEXT (column);

数据结构:B+树、hash表

设计原则:
(1)出现在where;order by;join的列
(2)区分度高的字段
(3)联合索引代替多个单列索引
(4)避免重复索引
(5)使用短索引

创建索引的原则:
(1)最左匹配原则,组合索引中非常重要的原则,使用最频繁的一列放在最左边,mysql会一直向右匹配直到遇到范围查询就停止。
(2)较频繁作为查询条件的字段才去创建索引,更新频繁的字段不创建索引
(3)区分度低的字段不适合创建索引
(4)尽量扩展索引,不要新建索引(联合索引代替多个单列索引)

创建索引的命令:
(1)create table时创建索引;
(2)alter table table_name add index index_name (column_list);
(3)create index index_name on table_name (column_list);

删除索引的命令:
alter table 表名 drop KEY 索引名
删除主键索引:alter table 表名 drop primary key(因为主键只有一个)

百万级别或以上的数据如何删除:
(1)先删除索引
(2)删除无用数据
(3)删除完成后重新创建索引

事务四大特性(ACID)原子性、一致性、隔离性、持久性?

事务是数据库管理系统(DBMS)执行过程中的一个逻辑单位,由一个有限的数据库操作序列构成。
只要满足一下四个特征的就属于事务,事务的四大特性ACID(原子性、一致性、隔离性、持久性)
(1)原子性:(undo log)
事务中整个操作要么全部完成,要么全部不完成。
(2)一致性:(通过原子性、隔离性、持久性来保证一致性)
在事务开始之前和事务结束以后,数据库的完整性约束没有被破坏。
(3)隔离性:
事务间的操作互不干扰。
(4)持久性:(redo log)
事务一旦完成,就永久保存。
mysql中关于事务的语句:
start trunsaction/begin --开启事务
savepoint 保留点 --创建保留点(即:还原点)
rollback to 保留点 --回滚
commit --提交
补充:
set autocommit=0 --设置mysql不自动提交更改
release 保留点 释放保留点

事务的并发?事务隔离级别,每个级别会引发什么问题,MySQL默认是哪个级别?

一个数据库可能拥有多个访问客户端,这些客户端都可以并发方式访问数据库。数据库中的相同数据可能同时被多个事务访问,如果没有采取必要的隔离措施,就会导致各种并发问题,破坏数据的完整性。
带来的问题:其实都是数据库读一致性的问题:
1)脏读:一个事务读取到了另外一个事务未提交的数据,读到其他事务未提交的“更新”数据。
2)不可重复读:同一个事务中,多次读取到的数据不一致。(其他事务提交的数据(update/delete))
3)幻读:一个事务读取到了另外一个事务已提交的数据,只是读到的是其他事务"插入”的数据。

事务的隔离级别:
READ UNCOMMITED(未提交读):一个事务可以读取到另一个事务未提交的修改。这会带来脏读、幻读、不可重复读问题。(基本没用)
READ COMMITED(提交读):一个事务只能读取另一个事务已经提交的修改。其避免了脏读,但仍然存在不可重复读和幻读问题。
REPEATABLE READ(可重复读):同一个事务中多次读取相同的数据返回的结果是一样的。其避免了脏读和不可重复读问题,但幻读依然存在。(对InnoDB也解决了幻读)
SERIALIZABLE(可串行化):最高级别,强制事务串行执行,对读取的每一行数据都加锁,可能导致大量的超时和锁争用的情况,只有在非常需要确保数据的一致性且可以接收没有并发的情况下,才会使用这一隔离级别。

mysql默认的隔离级别是可重复读

查询语句:show variables like 'tx_isolation';

如果要解决读一致性的问题,保证一个事务中前后两次读取数据结果一致,实现事务隔离,应该怎么做?
(1)在读取数据前,对其加锁,阻止其他事务对数据进行修改-LBCC(Lock Based Concurrency control)
(2)生成一个数据请求时间点的一致性数据快照(snapshot),并用这个快照来提供一定级别(语句级或事务级)的一致性读取-MVCC(multi version Concurrency control)
与实现原子性一样,回滚是利用的undo log,MVCC也是利用undo log,MVCC也是利用undo log,MVCC也是利用undo

InnoDB的锁:

锁的作用:
锁到底锁住了什么?是实现在索引记录上的。
(1)共享/排它锁(行锁):

  • 共享锁:(S锁)读锁,多个事务对于同一数据可以共享一把锁,都能访问到数据,但是只能读不能修改:读取数据时加S锁,共享锁之间不互斥,简记为:读读可以并行
    加锁:select * from student where id = 1 LOCK IN SHARE MODE;
    释放锁:commit/rollback;

  • 排他锁:(X锁)写锁,一个事务获取了一个数据行的排他锁,其他事务就不能再获取该行的锁(共享锁,排他锁)。排他锁与任何锁互斥,简记为:写读,写写不可以并行
    加锁:(1)自动:delete/update/insert默认加上X锁;(2)手动:select * from student where id = 1 FOR UPDATE;
    释放锁:commit/rollback;
    (2)意向锁(表锁):
    数据引擎自己维护的,用户无法手动操作意向锁。
    意向共享锁:(IS锁)表示事务准备给数据行加入共享锁,也就是说一个数据行加共享锁前必须先取得该表的IS锁。
    意向排他锁:(IX锁)表示事务准备给数据行加入排他锁,也就是说一个数据行加排他锁前必须先取得该表的IX锁。
    一个事务成功地给一张表加上表锁的前提:没有其他任何事务锁定了这张表的任意一行数据。 所以需要全表的扫描去检测是否有行锁,若表数据量特别大,扫描会非常费时,或者在扫描过程中有行锁加上了。因此引入意向锁,直接看意向锁就可以,提高加表锁的效率。

死锁:
死锁是指两个或多个事务在同一资源上相互占用,并请求锁定对方占用的资源,从而导致恶性循环。
——死锁有双重原因:真正的数据冲突;存储引擎的实现方式。
检测死锁:数据库系统实现了各种死锁检测和死锁超时的机制。InnoDB存储引擎能检测到死锁的循环依赖并立即返回一个错误。
死锁恢复:死锁发生以后,只有部分或完全回滚其中一个事务,才能打破死锁,InnoDB目前处理死锁的方法是,将持有最少行级排他锁的事务进行回滚。所以事务型应用程序在设计时必须考虑如何处理死锁,多数情况下只需要重新执行因死锁回滚的事务即可。
死锁影响性能:死锁会影响性能而不是会产生严重错误,因为InnoDB会自动检测死锁状况并回滚其中一个受影响的事务。
MyISAM避免死锁:
在自动加锁的情况下,MyISAM 总是一次获得 SQL 语句所需要的全部锁,所以 MyISAM 表不会出现死锁。
InnoDB避免死锁:

1.为了在单个InnoDB表上执行多个并发写入操作时避免死锁,可以在事务开始时通过为预期要修改的每个元祖(行)使用SELECT ... FOR UPDATE语句来获取必要的锁,即使这些行的更改语句是在之后才执行的。
2.在事务中,如果要更新记录,应该直接申请足够级别的锁,即排他锁,而不应先申请共享锁、更新时再申请排他锁,因为这时候当用户再申请排他锁时,其他事务可能又已经获得了相同记录的共享锁,从而造成锁冲突,甚至死锁
3.如果事务需要修改或锁定多个表,则应在每个事务中以相同的顺序使用加锁语句。 在应用中,如果不同的程序会并发存取多个表,应尽量约定以相同的顺序来访问表,这样可以大大降低产生死锁的机会
4.通过SELECT ... LOCK IN SHARE MODE获取行的读锁后,如果当前事务再需要对该记录进行更新操作,则很有可能造成死锁。
5.改变事务隔离级别

尽量使用较低的隔离级别;
精心设计索引, 并尽量使用索引访问数据, 使加锁更精确, 从而减少锁冲突的机会
选择合理的事务大小,小事务发生锁冲突的几率也更小
给记录集显示加锁时,最好一次性请求足够级别的锁。比如要修改数据的话,最好直接申请排他锁,而不是先申请共享锁,修改时再请求排他锁,这样容易产生死锁
不同的程序访问一组表时,应尽量约定以相同的顺序访问各表,对一个表而言,尽可能以固定的顺序存取表中的行。这样可以大大减少死锁的机会
尽量用相等条件访问数据,这样可以避免间隙锁对并发插入的影响
不要申请超过实际需要的锁级别
除非必须,查询时不要显示加锁。 MySQL的MVCC可以实现事务中的查询不用加锁,优化事务性能;MVCC只在COMMITTED READ(读提交)和REPEATABLE READ(可重复读)两种隔离级别下工作
对于一些特定的事务,可以使用表锁来提高处理速度或减少死锁的可能

MySQL的MyISAM与InnoDB两种存储引擎在,事务、锁级别,各自的适用场景?

**MyISAM表锁:**在执行查询语句前,会自动给涉及的所有表加读锁,在执行更新操作(UPDATE,DELETE,INSERT等)前,会自动给涉及的表加写锁。(不需要显式加锁)

显式加读锁: lock table table_name read;
显式加写锁: lock table table_name write;
解锁:unlock tables;

MyISAM读锁:会阻塞写,但不会阻塞读;
写锁:会阻塞读和写。
所以MyISAM适合做读为主的存储引擎。

查看锁的争用情况:

show open tables;
in_use:表当前被查询使用的次数。
name_locked:表名称是否被锁定。

show status likd "Table_locks%";
table_locks_immediate:
table_locks_waited:

InnoDB 行锁:
select语句并不会加锁;
update会加写锁

无索引行锁升级为表锁: where后的字段索引失效

SQL语句分为哪几类?

数据定义语言DDL(Data Ddefinition Language)CREATE,DROP,ALTER
主要为以上操作 即对逻辑结构等有操作的,其中包括表结构,视图和索引。

数据查询语言DQL(Data Query Language)SELECT
这个较为好理解 即查询操作,以select关键字。各种简单查询,连接查询等 都属于DQL。

数据操纵语言DML(Data Manipulation Language)INSERT,UPDATE,DELETE
主要为以上操作 即对数据进行操作的,对应上面所说的查询操作 DQL与DML共同构建了多数初级程序员常用的增删改查操作。而查询是较为特殊的一种 被划分到DQL中。

数据控制功能DCL(Data Control Language)GRANT,REVOKE,COMMIT,ROLLBACK
主要为以上操作 即对数据库安全性完整性等有操作的,可以简单的理解为权限控制等。

delete,truncate,drop:
(1)类型:delete属于DML,truncate和drop属于DDL
(2)回滚:delete可以回滚,但是truncate和drop不可以回滚
(3)删除内容:delete删除全部或者一部分数据,truncate删除所有数据,drop删除表结构和数据
(4)删除速度:delete很慢,需要逐行删除,truncate删除速度快,drop删除速度最快。

查询语句不同元素(where、jion、limit、group by、having等等)执行先后顺序?

编写顺序:	
SELECT DISTINCE
	<select list>
FROM
	<left_table> <join_type>
JOIN	
	<right_table> ON <join_condition>
WHERE
	<where_condition>
GROUP BY
	<group_by_list>
HAVING
	<having_condition>
ORDER BY
	<order_by_condition>
LIMIT
	<limit_params>

执行顺序:

	1、from 子句组装来自不同数据源的数据,所以为表创建别名,别的地方可以用;
	2、ON JOIN
	3、where 子句基于指定的条件对记录行进行筛选;
	4、group by 子句将数据划分为多个分组;
	5、使用聚集函数进行计算;    一定要知道他的执行顺序在group by后having之前
	6、使用 having 子句筛选分组;
	7、计算所有的表达式;
	8、select 的字段;
	9、使用 order by 对结果集进行排序
	10、LIMIT

数据类型

1.整数类型:tinyint(8位二进制),smallint(16位二进制),mediumint(24位),int(32位)
2.小数类型:float(4字节),double(8字节),decimal
3.日期类型:year,time,date,datetime,timestamp
4.文本,二进制类型:char(), varchar()
varchar与char的区别:
char:定长字符串,插入的数据长度小于固定长度,用空格填充;存取速度快(空间换时间),最多255个字符。
varchar:可变长,存取慢,最多65532
int(20):是指显示字符的长度。20表示最大显示宽度为20

什么是临时表,临时表什么时候删除?

CREATE TEMPORARY TABLE tab_name;
默认情况下,当你断开与数据库的连接后,临时表就会自动被销毁。当然你也可以在当前MySQL会话使用 DROP TABLE 命令来手动删除临时表。

7.MySQL B+Tree索引和Hash索引的区别?

索引的作用:提高数据查询效率
常见索引模型:哈希表、有序数组、搜索树
哈希表:键 - 值(key - value)。
哈希思路:把值放在数组里,用一个哈希函数把key换算成一个确定的位置,然后把value放在数组的这个位置
哈希冲突的处理办法:链表
哈希表这种结构适用于只有等值查询的场景。Hash 索引仅仅能满足"=",“IN"和”<=>"查询,不能使用范围查询。

B+树:
根据叶子节点的内容,索引类型分为主键索引和非主键索引。
主键索引的叶子节点存的是整行数据,主键索引也被聚簇索引。–select * from T where ID=500,主键查询方式,只需要搜索这棵B+树。
非主键索引的叶子节点存的是主键的值,被称为二级索引。select * from T where k = 5,普通索引查询方式,先搜索k索引树,得到ID(主键)的值,再到ID索引树搜索一次,回表。
一个数据页满了,按照B+Tree算法,新增加一个数据页,叫做页分裂,会导致性能下降。空间利用率降低大概50%。当相邻的两个数据页利用率很低的时候会做数据页合并,合并的过程是分裂过程的逆过程。
从性能和存储空间方面考量,自增主键往往是更合理的选择。

有哪些锁(乐观锁悲观锁),select 时怎么加排它锁?

悲观锁的特点是先获取锁,再进行业务操作,即“悲观”的认为获取锁是非常有可能失败的,因此要先确保获取锁成功再进行业务操作。通常所说的“一锁二查三更新”即指的是使用悲观锁。通常来讲在数据库上的悲观锁需要数据库本身提供支持,即通过常用的select … for update操作来实现悲观锁。当数据库执行select for update时会获取被select中的数据行的行锁,因此其他并发执行的select for update如果试图选中同一行则会发生排斥(需要等待行锁被释放),因此达到锁的效果。select for update获取的行锁会在当前事务结束时自动释放,因此必须在事务中使用。

这里需要注意的一点是不同的数据库对select for update的实现和支持都是有所区别的,例如oracle支持select for update no wait,表示如果拿不到锁立刻报错,而不是等待,MySQL就没有no wait这个选项。另外MySQL还有个问题是select for update语句执行中所有扫描过的行都会被锁上,这一点很容易造成问题。因此如果在MySQL中用悲观锁务必要确定走了索引,而不是全表扫描。

乐观锁也叫乐观并发控制,它假设多用户并发的事务在处理时不会彼此互相影响,各事务能够在不产生锁的情况下处理各自影响的那部分数据。在提交数据更新之前,每个事务会先检查在该事务读取数据后,有没有其他事务又修改了该数据。如果其他事务有更新的话,那么当前正在提交的事务会进行回滚。

乐观锁的特点先进行业务操作,不到万不得已不去拿锁。即“乐观”的认为拿锁多半是会成功的,因此在进行完业务操作需要实际更新数据的最后一步再去拿一下锁就好。

**乐观锁在数据库上的实现完全是逻辑的,**不需要数据库提供特殊的支持。一般的做法是在需要锁的数据上增加一个版本号,或者时间戳,然后按照如下方式实现:

乐观锁(给表加一个版本号字段) 这个并不是乐观锁的定义,给表加版本号,是数据库实现乐观锁的一种方式。

(1) SELECT data AS old_data, version AS old_version FROM …;

(2)根据获取的数据进行业务操作,得到new_data和new_version

(3)UPDATE SET data = new_data, version = new_version WHERE version = old_version

    if (updated row > 0) {

           // 乐观锁获取成功,操作完成

        } else {

           // 乐观锁获取失败,回滚并重试

    }

乐观锁在不发生取锁失败的情况下开销比悲观锁小,但是一旦发生失败回滚开销则比较大,因此适合用在取锁失败概率比较小的场景,可以提升系统并发性能

乐观锁还适用于一些比较特殊的场景,例如在业务操作过程中无法和数据库保持连接等悲观锁无法适用的地方。

11.非关系型数据库和关系型数据库区别,优势比较?

13.数据库的读写分离、主从复制,主从复制分析的 7 个问题?

主从复制分成三步:

1.master主库在事务提交时,会把数据变更作为实践events记录在二进制日志文件binlog中。
2.主库推送二进制日志文件binlog中的日志事件到从库的中继日志relay log
3.slave重做中继日志中的事件,将改变反映它自己的数据。

复制优势

1.主库出现问题,可以快速切换到从库提供服务。
2.读写分离,读操作走从库,写操作走主库。
3.从库执行备份,避免备份器件影响主库的服务。

14.使用explain优化sql和索引?

全值匹配是针对建立了复合索引的索引列,在查询条件中,复合索引的所有列都指定具体的列。
创建复合索引:
create index idx on userinfo(username,age,phone,gender);
执行全值匹配SQL:
explain select * from userinfo where username=‘1’ and age=1 and phone=‘1’ and gender=1 ;
使用explain语句可以模拟优化器执行SQL查询语句
结果如下:
| id | select_type | table | partitions | type | possible_keys | key | key_len | ref | rows | filtered | Extra|
(1)id:select查询的序列号,包含一组数字,表示查询中执行select子句或操作表的顺序

1)id相同,执行顺序由上至下
2)id不同,如果是子查询,id的序号会递增,id值越大优先级越高,越先被执行

(2)select_type:

1)SIMPLE 简单的select查询,查询中不包含子查询或者UNION
2)PRIMARY 查询中若包含任何复杂的子部分,最外层查询则被标记为PRIMARY
3)SUBQUERY 在SELECTWHERE列表中包含了子查询
4)DERIVED 在FROM列表中包含的子查询被标记为DERIVED(衍生),MySQL会递归执行这些子查询,把结果放在临时表中
5UNION 若第二个SELECT出现在UNION之后,则被标记为UNION:若UNION包含在FROM子句的子查询中,外层SELECT将被标记为:DERIVED
6UNION RESULT 从UNION表获取结果的SELECT

(3)table:当前执行的表
(4)type:非常重要,可以看有没有走索引:
从最好到最差依次是:system > const > eq_ref > ref > range > index > all

1)system: 表只有一行记录(等于系统表),这是const类型的特列,平时不会出现,这个也可以忽略不计
2)const: 表示通过索引一次就找到了,const用于比较primary key 或者unique索引。因为只匹配一行数据,所以很快。如将主键置于where列表中,MySQL就能将该查询转换为一个常量。
3)eq_ref: 唯一性索引扫描,对于每个索引键,表中只有一条记录与之匹配。常见于主键或唯一索引扫描
4)ref: 非唯一性索引扫描,返回匹配某个单独值的所有行,本质上也是一种索引访问,它返回所有匹配某个单独值的行,然而,它可能会找到多个符合条件的行,所以他应该属于查找和扫描的混合体。
5)range: 只检索给定范围的行,使用一个索引来选择行,key列显示使用了哪个索引,一般就是在你的where语句中出现between<>in等的查询,这种范围扫描索引比全表扫描要好,因为它只需要开始于索引的某一点,而结束于另一点,不用扫描全部索引。
6indexFull Index Scan,IndexAll区别为index类型只遍历索引树。这通常比ALL快,因为索引文件通常比数据文件小。(也就是说虽然allIndex都是读全表,但index是从索引中读取的,而all是从硬盘读取的)
7allFull Table Scan 将遍历全表以找到匹配的行

(5)possible_keys 和 key

1)possible_keys 显示可能应用在这张表中的索引,一个或多个。查询涉及到的字段上若存在索引,则该索引将被列出,但不一定被查询实际使用。
2key:实际使用的索引,如果为NULL,则没有使用索引。(可能原因包括没有建立索引或索引失效)
3)查询中若使用了覆盖索引(select 后要查询的字段刚好和创建的索引字段完全相同),则该索引仅出现在key列表中

(6)key_len 表示索引中使用的字节数,可通过该列计算查询中使用的索引的长度,在不损失精确性的情况下,长度越短越好。key_len显示的值为索引字段的最大可能长度,并非实际使用长度,即key_len是根据表定义计算而得,不是通过表内检索出的.
(7)ref 显示索引的那一列被使用了,如果可能的话,最好是一个常数。哪些列或常量被用于查找索引列上的值。
(8)rows:根据表统计信息及索引选用情况,大致估算出找到所需的记录所需要读取的行数,也就是说,用的越少越好
(9)Extra:包含不适合在其他列中显式但十分重要的额外信息
索引失效的情况:
在查询语句前加explain关键字,查看type类型是否为all,是则没有用到索引,否则使用了索引

(1).全值匹配 ,对索引中所有列都指定具体值。该情况下,索引生效,执行效率高。
(2).最左前缀法则:如果索引了多列,要遵守左前缀法则。指的是查询从索引的左前列开始,并且不跳过索引中的列,否则索引失效。
(3).范围查询右边的列,不能使用索引 ,否则破坏后面字段的索引。
(4). 不要在索引列上进行运算操作, 索引将失效。
(5). 字符串不加单引号,造成索引失效。【在查询是,没有对字符串加单引号,MySQL的查询优化器,会自动的进行类型转换,造成索引失效】
(6). 尽量使用覆盖索引,避免select *。尽量使用覆盖索引(只访问索引的查询(索引列完全包含查询列)如:select id from user,id是user的某个索引),减少select *(7).or分割开的条件, 如果or前的条件中的列有索引,而后面的列中没有索引,那么涉及的索引都不会被用到。但是and不会受影响
	示例,name字段是索引列 , 而createtime不是索引列,中间是or进行连接是不走索引的
(8).%开头的Like模糊查询,索引失效。 如果仅仅是尾部模糊匹配,索引不会失效。如果是头部模糊匹配,索引失效。【如果使用了,可以应用索引覆盖来解决。】
(9). 如果MySQL评估使用索引比全表更慢,则不使用索引。
(10). is NULLis NOT NULL 有时索引失效。会根据表的具体情况来决定是否使用索引。
(11). in 走索引, not in 索引失效
(12). 单列索引和复合索引。 尽量使用复合索引,而少使用单列索引

15.MySQL慢查询怎么解决?

开启慢查询日志

配置项:slow_query_log

可以使用show variables like ‘slov_query_log’查看是否开启,如果状态值为OFF,可以使用set GLOBAL slow_query_log = on来开启,它会在datadir下产生一个xxx-slow.log的文件。

设置临界时间
配置项:long_query_time
查看:show VARIABLES like ‘long_query_time’,单位秒
设置:set long_query_time=0.5
实操时应该从长时间设置到短的时间,即将最慢的SQL优化掉
查看日志,一旦SQL超过了我们设置的临界时间就会被记录到xxx-slow.log中

慢查询的优化首先要搞明白慢的原因是什么? 是查询条件没有命中索引?是load了不需要的数据列?还是数据量太大?

所以优化也是针对这三个方向来的,
首先分析语句,看看是否load了额外的数据,可能是查询了多余的行并且抛弃掉了,可能是加载了许多结果中并不需要的列,对语句进行分析以及重写。
分析语句的执行计划,然后获得其使用索引的情况,之后修改语句或者修改索引,使得语句可以尽可能的命中索引。
如果对语句的优化已经无法进行,可以考虑表中的数据量是否太大,如果是的话可以进行横向或者纵向的分表

16.什么是 内连接、外连接、交叉连接、笛卡尔积等?

19.mysql 高并发环境解决方案?

20.数据库崩溃时事务的恢复机制(REDO日志和UNDO日志)?

sql优化:

(1)大批量插入数据: 使用load命令导入数据的时候,1)主键顺序插入;2)关闭唯一性校验(set unique_checks=0);3)手动提交事务(set autocommit=0)
(2)insert优化
1)如果我们有多条insert语句对同一个表的相同字段进行插入,则建议整合为一个insert语句,例如insert into test values (1,2),(3,4),(5,6),因为这样可以减少数据库的链接,关闭操作的消耗,使得效率提高。
2)在事务中进行数据插入
3)数据有序插入
(3)order by优化:using filesort / using index(效率高)
1)按多字段排序要么都升序,要么都降序;排序的顺序需要和索引的顺序保持一致。(和where不同)
(4)group by优化:
1)执行order by null禁止排序
2)创建索引
**(5)子查询的优化:**尽量使用多表连接查询,减少嵌套子查询。子查询在执行的时候 数据库需要位内层查询语句的查询结果建立一个临时表,然后外层语句查询临时表,所以子查询的效率比较低,而连接查询就不存在这个问题。
**(6)or 优化:**建议使用union替换or
**(7)limit优化(**分页查询):
mysql为分页查询提供了很方便的关键字limit,但这个关键字在数据量较大时,却很低效。
“limit m,n”关键字的意思是,从第m行开始,扫描满足条件的n个偏移行。若需从第1行开始,则不需要指定m值。
迅速定位起始ID,利用主键索引,加快扫描速度。
1)select * from tb_item t, (select id from tb_item order by id limit 2000000,10) a where t.id=a.id;
2)select *from tb_item where id > 200000 limit 10;
(8)使用sql提示:
create index idx_seller_name on tb_seller(name);
1)use index(index_name) 提供参考,不一定会使用索引 select * from tb_seller use index(idx_seller_name) where name =‘小米科技’;
2)ignore index(index_name) select * from tb_seller ignore index(idx_seller_name) where name =‘小米科技’;
3)force index 一定会走索引。走全表扫描比索引快的话,会走全表扫描。

21.MySql日志

分类:错误日志,查询日志,慢查询日志,二进制日志。

show global variables like '%log%';
  1. 错误日志:默认开启,记录了服务器启动关闭信息,运行错误信息,时间调度器运行一个事件时产生的信息,在服务器上启动进程产生的信息。
  2. 查询日志:默认关闭,记录用户所有的操作,包括增删改查等信息。
general_log=1   --打开查询日志开关
general_log_file=file_name  --存放的文件名
  1. 慢查询日志:默认关闭,记录执行时间超过指定时间的查询语句,可以查找出哪些查询语句的执行效率很低,以便于优化。
slow_query_log=1
slow_query_log_files=slow_query.log
long_query_time=10 --配置查询的时间限制,超过这个时间将认为是慢查询,需要记录日志,默认10s
可以通过 show variables like 'long_query_time';查询

查看慢查询日志:

1.直接通过cat指令查询日志文件,tail -f slow_query.log 实时查看日志内容
2.如果日志内容很多,通过mysql自带的mysqldumpslow工具,对慢查询日志进行分类汇总。
  1. 二进制日志(BINLOG):默认关闭。通过配置文件my.conf。
 log_bin=mysqlbin;
 binlog_format=格式

记录了所有DDL(数据定义语言)和DML(数据操纵语言)语句,但是不包括数据查询语句。此日志对于灾难时的数据恢复起着极其重要的作用,Mysql的主从复制,就是通过BINLOG实现的。
日志格式:

 1.STATEMENT(SQL语句);通过mysqlbinlog工具查看
 2.ROW:记录了每一行的数据变更,不是SQL语句。
 3.MIXED:混合了STATEMENT和ROW两种格式。(默认)

删除日志:

1.reset master:删除全部binlog日志,删除之后,日志编号将从xxxx.0000001重新开始
2.purge master logs to 'myssqlbin.******',将删除*****编号之前的所有日志
3.purge master logs before'yyyy-mm-dd hh24:mi:ss',该命令删除日志为“yyyy-mm-dd hh24:mi:ss”之前产生的日志
4.设置--expire_logs_days=#, 设置过期天数,过了指定的天数后的日志会被自动删除。

21条MySQL性能调优经验

为查询缓存优化你的查询
EXPLAIN你的SELECT查询
当只要一行数据时使用LIMIT 1
为搜索字段建索引
在Join表的时候使用相当类型的例,并将其索引
千万不要 ORDER BY RAND()
避免 SELECT *
永远为每张表设置一个 ID
使用 ENUM 而不是 VARCHAR
从 PROCEDURE ANALYSE() 取得建议
尽可能的使用 NOT NULL
Prepared Statements
无缓冲的查询
把 IP 地址存成 UNSIGNED INT
固定长度的表会更快
垂直分割
拆分大的 DELETE 或 INSERT 语句
越小的列会越快
选择正确的存储引擎
使用一个对象关系映射器(Object Relational Mapper)
小心“永久链接”

视图

所谓视图,本质上是一种虚拟表,在物理上是不存在的,其内容与真实的表相似,包含一系列带有名称的列和行数据。

视图的特点如下:

  • 视图的列可以来自不同的表,是表的抽象和在逻辑意义上建立的新关系。
  • 视图是由基本表(实表)产生的表(虚表)。
  • 视图的建立和删除不影响基本表。
  • 对视图内容的更新(添加,删除和修改)直接影响基本表。
  • 当视图来自多个基本表时,不允许添加和删除数据。

sql约束

  • NOT NULL: 用于控制字段的内容一定不能为空(NULL)。
  • UNIQUE: 控件字段内容不能重复,一个表允许有多个 Unique 约束。
  • PRIMARY KEY: 也是用于控件字段内容不能重复,但它在一个表只允许出现一个。
  • FOREIGN KEY: 用于预防破坏表之间连接的动作,也能防止非法数据插入外键列,因为它必须是它指向的那个表中的值之一。
  • CHECK: 用于控制字段的值范围。
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值