我的MySQL
主要来自
《高性能MySQL(第3版)》
《MySQL管理之道:性能调优、高可用与监控(第2版)》
《MySQL 8 Cookbook:Over 150 recipes for high-performance database querying and administration》
以及MySQL的官方文档
相关名称解释:
schema:database and table structure
shared lock,共享锁,S锁:允许其他事务读取被锁定的对象,其他事务也可以获取另一个此对象的共享锁,但是不允许写操作。
exclusive lock,排它锁,X锁:
intention lock,意向锁:作用在表上(是表级锁),用于指明事务要获取行锁的类型。不同的事务可以在同一个表上获取不同的意向锁,但是第一个获取了表IX锁的事务,会阻止其他想要获取S锁和X锁的。相反,如果第一个获取了表IS锁的事务,仅阻止其他想要获取X锁的事务。
来自《高性能MySQL(第3版)》
1、MySQL的存储引擎
可是使用语句查看table的存储信息:show table status like ‘tablename’;
InnoDB引擎:被设计用来处理大量的短期(short-lived)事务,当然在非事务性存储也很流行。
MyISAM:设计简单,对整个表加锁,不支持行锁。
其他引擎有Archive、Blackhole、CVS、Federated、Memory等。
大多数情况下选择InnoDB,除非要用到InnoDB不具备的特性。例如,不在乎并发与扩展,也不在乎崩溃后数据丢失,却对InnoDB的空间占用比较敏感,可选择MyISAM。
2、选择存储引擎的几个需要考虑的因素。
事务:比如无需事务、且主要使用select和insert的日志型应用,则可使用MyISAM。
备份:
崩溃恢复:
其他特性:如地理空间搜索、聚簇索引等等
3、关于InnoDB的几个特点
table是基于聚簇索引建立的,主键查询效率非常高,但是有二级索引问题。
采用MVCC支持高并发,并且实现了4个事务隔离级别,默认是Repeatable Read。
4、死锁与解决方法
在资源上的相互占用导致死锁。发生死锁时,只有部分或完全回滚其中一个事务,才能打破死锁。
数据库提供了死锁检查和死锁超时。InnoDB目前处理死锁的方式是,将持有最少行级排它锁的事务进行回滚。
5、关于事务日志
存储引擎只在内存中修改数据,并不立即把数据持久化到磁盘,而是把事务日志持久化到磁盘。事务日志采用追加方式,并且磁盘是小区域的顺序IO,执行效率高。内存中的数据在后台择机刷新到磁盘。如果此时宕机,重启后引擎会恢复这部分数据。
6、事务中混合使用存储引擎
事务是由存储引擎实现的,所以如果事务中涉及不同的存储引擎,那这个事务是不可靠的。比如混合使用InnoDB和MyISAM,在回滚时非事务型无法撤销。
7、InnoDB的显示和隐式锁
显示锁:Select … Lock in share mode;Select…for update。MySQL也支持Lock table和Unlock
table语句。
8、InnoDB的两阶段锁定协议
在事务执行过程中,可以随时执行锁定。只有执行Commit或Rollback时才会释放锁,并且所有锁是同时释放。
9、多版本并发控制:MVCC
可以认为MVCC是行锁的变种,它的实现是通过保存数据在某个时间点的快照实现的。与其相关的事务隔离级别是Repeatable Read。
10、MySQL基准测试的指标都有那些
吞吐量:单位时间内事务处理数,主要是针对在线事务处理(OLTP)的吞吐量,常用单位是TPS:每秒事务数,或TPM:每分钟事务数。
响应时间或延迟:测试任务所需的整体时间,通常计算平均相应时间,最小相应时间、最大相应时间及百分比。常用百分比响应时间来描述最大相应时间,如95%的相应时间是5毫秒,表示95%的任务可以在5毫秒内完成。
并发性:需要关注在并发增加时,吞吐量是否下降,响应时间是否变长。
可扩展性:简单说就是给系统增加一倍资源,是否可同样增加一倍的吞吐量。
11、一些测试工具
集成式测试工具:
ab:一个Apache Http服务器的基准测试工具。
http_load:类似ab
JMeter
MySQL测试工具:
MySQLslap
Sql-bench
Super smack
Database Test Suite
Sysbench
12、关于“性能优化”的一个前置知识:任务所需的时间
性能就是完成任务的所需时间,即响应时间。而非“每秒查询次数”“cpu利用率”“可扩展性”之类。
执行任务包括两个时间:等待时间和执行时间。当谈到优化任务执行时间时,需要从这两个完全不同的角度去考虑。
比如任务执行时间优化,优化去掉一些子任务、提升子任务时间等。
13、关于选择优化的数据类型
更小的通常更好:占用空间少,磁盘、内存、cpu缓存的空间。
简单的更好:使用内建类型存储日期或时间;使用整数存储IP地址。
尽量避免NULL:对NuLL很难优化,且进行统计和比较都会复杂。也有例外,Null对于InnoDB列的稀疏数据有很好的空间利用率)
14、关于varchar(5)和varchar(200)
如果存储hello,那更短的列会有优势吗?事实证明其优势很大,更长的列占用更多的内存,MySQL内部会分配固定大小的内存块来保存内部值。
15、关于Alter table
【略】
16、MySQL索引有哪些类型?
B-tree索引:大多数引擎都支持此类型索引,但是又有所区别,NDB使用T-Tree,InnoDB使用B+Tree。
Hash索引:MySQL中只有Memory引擎支持Hash索引。扩展,InnoDB支持“自适应Hash索引“(在此不讨论)。
R-tree空间数据索引:MyISAM支持空间索引,可用作地理数据存储。
全文索引:查找的是文本中的关键字,而不是比较索引的值。
第三方存储引擎使用的自定义索引。
17、索引的优点
1、减少服务器扫描的数据量。
2、帮助服务器避免排序和临时表。
3、将随机IO变为顺序IO。
18、高性能索引策略
从以下方面考虑索引的使用策略:
独立的列:索引列不能是表达式的一部分,也不能是函数的参数。
前缀索引和索引选择性:平衡一下前缀索引和索引选择性两者的关系。
多列索引:这里涉及一个“索引合并“的概念,
选择合适的索引列顺序:对B-tree来说,最左顺序使用索引原则。但是,把选择性最好的列放置到最左是通用原则吗?在某些特殊场合下,避免随机IO和排序可能更重要一些。
聚簇索引:这不是索引类型,而是数据存储方式。在InnoDB中,聚簇索引在同一结构中保存了B-tree索引和数据行。
覆盖索引:如果索引中已经包含所需数据,则称为覆盖索引。
使用索引扫描做排序:
压缩(前缀压缩)索引:MyISAM使用前缀压缩来减少索引的大小。
冗余和重复索引:需要消除
未使用的索引:排查并消除。通过分析索引的使用频率(可能需要打开某开关)
索引和锁:虽然InnoDB基于索引的行锁开销很小,但是依然要尽可能减少被锁定的行数。被锁定的行越多,锁争用会减少并发性。
19、关于InnoDB中的聚簇索引
InnoDB通过主键聚集数据,如果没有主键,InnoDB会选择一个唯一的非空索引替代,如果没有这样的索引,InnoDB会隐式定义一个主键来作为聚簇索引。
聚簇索引的几个优点:
相关的数据保存在一起,减少IO次数
数据访问更快,从聚簇索引中获取数据通常比非聚簇索引快。
使用覆盖索引扫描的查询可直接使用页节点中的主键值,避免二次索引数据。
聚簇索引的缺点:
聚簇索引最大限度的提高IO密集型应用性能,但是如果都是基于内存的访问,顺序就不重要了。
插入速度严重依赖插入顺序。
更新聚簇索引代价较高。
插入新行(或主键被更新)时,如果需要移动行,则可能面临“页分裂”问题。
可能导致全表扫描变慢,尤其是行比较稀疏,或页分裂导致存储不连续的时候。
二级索引占用空间可能更大,因为在二级索引包含行的主键列。
二级索引访问需要两次索引查找。
20、一些啥玩意,看看吧!
关联子查询:?(尤其是In(select ))改造。
Union的局限性:union导致生成临时表。
索引合并:?
等值传递:?例如非常大的In()列表。
并行执行:?5.5版本不支持并行执行,8版本呢?需要考察。
哈希关联:?MySQL不支持哈希关联,所有关联都是嵌套循环关联。MariaDB实现了真正的哈希关联。
松散索引扫描:?MySQL不支持松散索引扫描,也就无法按照不连续的方式扫描一个索引。
最大值和最小值优化:使用索引的有序特性,放弃分组函数,使用limit 1来替代。
查询优化器提示(hint):最好不使用这个,因为数据库是不断升级的,可能导致一些系统级优化变得无效,并且代码维护起来也比较繁琐。
21、关于优化Limit语句
如limit 10000,20,前面10000条记录被抛弃,只返回后20条,这样的代价很高。可以从以下方面考虑:
尽量的使用索引覆盖和延迟关联。
转化为已知位置的查询,通过where的某些字段的条件。
依据某字段(如注解,某索引)的顺序特性,将前面的查询结果作为后续分页查询的where条件。
多获取1条数据(21条),如果存在第21条,则可以进行“下一页”如果不存在第21条,则无需再检索下一页。
应用程序缓存。
22、关于优化Union
MySQL(老版本这样,新版本呢?)总是通过创建并填充临时表的方式执行union,并且默认使用distinct去重,这个代价也很大。此时的优化是使用union all,避免唯一性检查。
临时表是避免不了的(吗?,看看新版本)
23、大数据量的扩展性,一般有下面两个策略
全量扫描数据、不要任何索引:考虑顺利IO和索引开销。
索引数据,并分离热点
24、MySQL中重要的缓存
以下缓存相对比较重要:
InnoDB缓冲池
InnoDB日志文件和MyISAM数据的操作系统缓存
MyISAM健缓存
查询缓存
无法手工分配的缓存,如二进制日志和表定义文件的操作系统缓存
其他缓存相对占用空间较小
25、MySQL的查询缓存检查
【内容部分来自《深入分布式缓存从原来到实践》】
相关的命令:
show variables like‘query_cache%’
show status like ‘Qcache%’
Query Cache命中率= Qcache_hits/(Qcache_hits +Qcache_inserts)
26、每个连接需要多少内存
【TODO】
27、线程缓存(thread_cache_size)
设置“线程池大小”的概念,新连接进入时可以从线程缓存中取一个线程,并分配给这个新连接。
Thread_cache_size:可缓存的线程数。可以通过show status
like ‘threads_created’查看以下状态。下面还有描述。
28、表缓存(table_cache_size)
类似线程缓存,可以理解为对表结构(.frm文件)的缓存。这个参数对InnoDB的重要性非常小,InnoDB不依赖这个信息做很多的事情。
InnoDB有自己的表缓存:Data Dictionary。
可以设置的大一些,没啥影响。
29、InnoDB事务日志
关于日志文件大小,有这样两个参数:
Innodb_log_file_size:默认5M
Innodb_log_files_in_groups:默认2
默认总共10M,在实际生产环境中过小,可以调高到几百兆或GB。尤其是8版本中,已经进行优化,log文件设置的大一些没毛病!
日志缓冲区参数:
innodb_log_buffer_size:默认1M,相对有点儿小。10几M或几十M都正常。此参数对日志IO有影响。
日志刷新到log文件(即持久化)参数:
innodb_flush_log_at_trx_commit:
0:每秒持久化到文件,并且刷新。与commit无关。
1:每次commit,这个是默认值,比较安全
2:每秒持久化,但并不刷新。与0的区别是MySQL宕机也不会丢失数据。但是如果服务器挂了,会导致一些事务丢失。
30、]InnoDB如何打开和刷新数据文件和日志
【TODO,很重要,回头看,略】
31、InnoDB表空间
【TODO、看看新版本的定义】
32、InnoDB的双写缓冲
【TODO,再看看】
很多文件系统做了同样的事情,没必要让InnoDB再做一遍,所以可禁用:innodb_doublewrite = 0。
32、InnoDB并发配置:innodb_thread_concurrency
限制一次性可以有多少线程进入内核,0表示不限制。
可参考一下公式:并发值=cpu数量*磁盘数量*2
34、MySQL的二进制日志参数
sync_binlog参数:
0:表示MySQL不刷新,交由操作系统自己决定什么时候持久化。
>0:表示每多少次二进制日志写操作进行一次持久化,1是个很安全的设置。
机制与事务日志类似,但是整体开销比事务日志要昂贵很多。设置为1,对性能损害可能很大。要慎重。
35、Binlog的格式,需要谨慎设置
有三种格式:Statement、Row、Mixed
Statement:记录sql语句。
Row:记录数据的实际变更
Mixed:默认是Statement,但在以下情况下是Row格式:
NDB引擎的DML操作
使用了UUID函数
自增字段更新
包含了Insert Delayed语句
使用了用户定义函数(UDF)
使用了临时表
*Repeatable-Read隔离级别下,建议设置Row格式。Read-Committed隔离级别下Mixed和Row效果一样,都是Row格式。
*Row相关的另一个参数binlog_row_image = minimal,让binlog只记录影响后的行,从而降低binlog增长量。
36、innodb的最重要的两个配置参数
innodb_buffer_pool_size
innodb_log_file_size:注意:在版本8,这个文件要稍微大一些,没啥影响。
37、关于max_connections配置
如果不能执行查询,那多打开一个连接是没有好处的。所以遇到“太多的连接错误”是一种快速且代价小的失败方式。
可观察“max_used_connections”和”max_used_connectios_time”来看一下历史统计信息。
*需要警惕一下应用停机/重启时连接释放和重连问题,如果未释放干净,可能导致重连超限。
38、关于thread_cache_size配置
跟线程数量的波动有关,不用设置太大,因为保持太大空闲线程也没啥卵用。一个相关的状态变量是“slow_launch_threads”,如果这个值比较大,则说明有些情况导致延迟了连接分配新线程。
39、关于expire_logs_days配置
二进制日志过期时间。别手工rm删除日志文件,导致MySQL很迷惑自己的处理能力:)。
40、关于max_allowed_packet
允许服务器接收与发送的最大数据包,默认值太小,但是设置的太大也有危险。如果太小,在复制时可能出现问题,备库不能接收主库发过来的复制数据。
41、关于优化排序的配置
two-pass和single-pass排序算法
max_length_for_sort_data:如果查询中所需要的列和order by列总大小(按字段定义,非实际存储数据的大小),则使用two-pass算法排序。否则使用single-pass算法。
max_sort_length:当对blob和text排序时,只使用前缀,忽略剩余的值。此变量指定前缀大小。
42、关于排序缓存(sort buffer)和读缓存(read buffer)需要设置吗?
默认值就很好,无需配置
。。。。。。。
来自《MySQL管理之道:性能调优、高可用与监控(第2版)》
46、MySQL有哪些形式的锁
有以下三种级别的锁:
表级锁:开销小、加锁快、不出现死锁;粒度大,冲突概率高,并发度低。MyISAM引擎属于这种类型。
行级锁:
页面锁:
47、Per_thread_buffers优化
有这样的几个相关参数:
read_buffer_size:表的顺序扫描(如全表扫描)时,会临时缓冲到这个区域,再返回给上层调用者。
read_rnd_buffer_size:与上面的顺序读取不同,这个是随机读取的缓冲区。
sort_buffer_size:order by或group by字段没用到索引,可用此参数增加每个线程的分配缓冲区来提高性能,同时出现“user filesort”,遇到这样的提示则需要优化。
thread_stack:线程堆栈大小
join_buffer_size:join中的关联字段没索引,会使用这个区域提高性能,也同时出现“using join buffer”,遇到这样的提示就需要优化了。
binlog_cache_size:如果没有大事务,就不用太大。
max_connections:最大连接数
per_thread_buffers的内存计算公式是:sum(上面的buffer size)* max_connections。
48、Global_buffers优化
有这样的几个相关参数:
innodb_buffer_pool_size:默认才128M,太小太小,参考整个内存的70%-80%
innodb_additional_mem_pool_size:数据字典缓存。10几M就够。
innodb_log_buffer_size:日志缓冲区大小,与innodb_flush_log_trx_commit参数联合使用。
key_buffer_size:MyISAM引擎参数
query_cache_size:缓存select语句和结果集大小的参数。与query_cache_type联合使用,如果频繁的写操作,则最好关闭这个缓存,避免缓存过于频繁的刷新。
49、关于初始化参数中的:innodb_page_size
配置InnoDB数据页大小,默认16K。书中的案例:相比16k而言,8k的cpu压力高一些,select吞吐量也高。
50、关于“谨慎”使用分区表功能
分区字段必须属于主键字段
where后面的字段必须是分区字段,否则会在所有分区全部扫描一遍。
51、简要说明一下MySQL的事务实现
MySQL在进行事务处理的时候,采用日志先行的方式保证事务可快速并持久的运行,即写数据前,先写日志,过程如下:
开始事务时记录该事务的LSN日志序列号
执行事务时,往innodb_log_buffer里插入事务日志(redo log)
当事务提交时,将日志缓存中的事务日志刷新到磁盘(依赖另一个参数)。
除了事务日志,数据库还会记录一定量的撤销日志(undo log),用于处理回滚。
事务提交后,首先刷新binlog,然后再刷新redo log。【请看下面的问题】
52、数据库操作过程,会出现以下问题。也是事务隔离级别需要对付的几个问题
更新丢失,Lost Update
脏读,Dirty Reads
不可重复读,Non-repeatable Reads
两次更新问题,Second lost updates problem
幻读,Phantom Reads
53、数据库的四个事务隔离级别
未授权读取,Read Uncommitted
授权读取,Read Committed
可重复读,Repeatable Read
序列化,Serializable
54、关于“间隙锁”
间隙锁主要是防止幻读,用在Repeatable Read隔离级别。指的是,当对数据进行条件查询、范围检索时,对其范围内的也许并不存在的值进行加锁。其对高并发、且范围更新的业务有较大影响。
其实Repeatable Read的隔离级别就比较高,对高并发还是有影响的。
55、系统性能评估工具
vmstat、sar、iostat、netstat、free、ps、top、mpstat
dstat、collectl
淘宝的Tsar
56、一些常用的性能指标
CPU:
cpu使用率
%us:应用程序(用户空间)所花费的CPU百分比
%sy:系统(内核)所花费的CPU百分比
%ws:I/O等待所需的CPU时间总和
%id:CPU空闲百分比
%ni:Nice时间,花费在执行re-nicing(改变进程执行顺序和优先级)的CPU百分比。
内存指标:
空闲内存、交换空间使用
磁盘性能指标
磁盘I/O等待
队列平均长度
平均等待时间
每秒传输的数量
每秒读写块的数量
每秒读写字节的数量
57、高可用方案
MMM、MHA
。。。。。。。。。。
来自《MySQL 8 Cookbook:Over 150 recipes for high-performance database querying and administration》
58、获取Database和Table的信息/Getting information about databases and tables
这些信息来自于Information_schema,主要包括两类信息:
静态表元数据,static table metadata:Table_Schema、Table_Name、Table_Type、Engine。
动态表元数据,Dynamic table metadata:AUTO_INCREMENT,
AVG_ROW_LENGTH, and DATA_FREE。收集动态信息是有些成本的。
59、关于Common table expressions(CTE)
【忽略】
60、关于Generated columns
【忽略】
61、关于Window functions
【忽略】
62、关于Repeatable Read的几点知识
当一个事务开始时并执行了第一个读时,会创建一个读视图并保持打开,直到事务结束。为了提供前后一致的查询结果,InnoDB使用行版本和UNDO信息。称为MVCC-Multi-Version Concurrency Control。
63、Locking
【很重要的一章,其中参考了MySQL official doc】
MySQL有两种类型的锁:
内部锁Internal locking:MySQL内部用于管理多会话导致的表内容挣用。
外部锁External locking:客户端会话可以直接获取表锁,阻止其他会话访问表。
内部锁主要包括两种类型:
行级锁Row-level locks:把访问的行锁定,允许多会话同时写访问,适用于多用户、高并发、OLTP应用程序。只有InnoDB支持行级锁。
表级锁Table-level locks:MyISAM、MEMORY、MERGE
table使用表级锁。适用于只读、读非常多、单用户场景。
64、External Locking
使用Lock table和Unlock table来控制锁,分读锁和写锁。
READ读锁:允许其他会话读访问,阻塞所有会话写访问,其他会话也可以同时获得读锁,读锁是共享锁(shared lock)。
WRITE写锁:只允许当前会话读写,阻塞其他会话读/写访问,其他会话也不可以同时获取任何锁,写锁是排它锁(exclusive
lock)。
使用Unlock table语句或会话结束,可释放锁。
语法:
Lock tables table_name [READ|WRITE]
Unlock tables
FLUSH TABLES WITH READ LOCK; 相当于冻结了整个数据库。
65、锁队列Locking queue
1、只有共享锁可以同时作用在表上
2、如果已有共享锁,随后有请求获取排它锁,那这个排它锁会被放入一个队列,直到共享锁被释放。
3、只要锁队列中有锁请求,那么随后的锁请求都会被放入队列。
4、
4.1、InnoDB在进行读/写表的过程中,会获取元数据锁。
4.2、如果此时第二个事务申请写锁(lock table write),那此请求会被放入锁队列。
4.3、如果此时有第三个事务仅仅是想读数据,那也会别阻塞,也会被放入锁队列。
上述规则还是挺有意思的,总之,最好别使用lock table。因为随后的事务会被放入队列,而不是“直接错误”。超级危险。
66、InnoDB Locking
【很重要的一章】
67、二进制日志Binary Logging
数据和结构变化都会记录到二进制日志中。二进制日志可用于:
Replication复制:主从复制。
Point-in-time recovery时间点恢复。
日志格式(binlog_format)有三种:Row、Statement、Mixed
68、Backup and Restoring,备份与恢复
【忽略】
69、关于复制-Replication的一些拓补结构(topologies)
主从复制master-slave replication
链复制chain replication:masteràrelay masteràslave。
主主复制master-master replication、
多源复制multi-source replication:一个从服务可以接受来自多个主服务的数据。
70、关于延迟复制(delayed Replication)
主要是防止严重的应用层问题(如drop table等)被快速传递到从库。
71、关于半同步复制(semi-synchronous replication)
默认是异步复制的,Master不关心从机是否进行正常的复制,这可能有数据丢失风险。
半同步复制是Master确保至少一台Slave已经收到了“writes”。
全同步复制是Master保证所有Slave提交事务。
72、关于日志
MySQL日志包括以下类型(注意:是MySQL的日志,不是存储引擎的):
错误日志,error log
通用查询日志,general query log
慢查询日志,slow query log、
二进制日志,binary logs、
中继日志,relay logs
DDL logs
InnoDB相关的日志:
Redo Log
Undo Log
73、关于性能调整,相关的概念有以下
执行计划,explain plan
基准查询和服务,Benchmarking queries and server
增加索引,Adding indexes
看不见的索引,Invisible index:如果要删除索引,可以先让它Invisible,观察一下删除索引的影响。
降序索引,Descending index:相对Ascending index(升序索引),可定义降序索引。
慢查询分析,Analyzing slow queries using pt-query-digest
优化数据类型,Optimizing datatypes
移除重复和冗余索引,Removing duplicate and redundant indexes
检查索引的使用,Checking index usage
控制查询优化器,Controlling the query optimizer
使用索引暗示,Using index hints
使用资源分组,Using resource groups
使用performance_schema
使用sys schema
74、关于Secondary indexes
Primary key(clustered index)和Secondaryindexes
75、用put-query-digest分析慢查询
不只是慢查询日志,这个工具还可以通过多种渠道收集查询:
慢查询日志,slow query log
通用查询日志,general query log
过程列表,process list
二进制日志,Binary log
TCP dump
来自《MySQL Documentation——MySQL Reference Manual》
76、关于优化
很多很多,包括从以下方面考虑优化,每个方面都是很大的课题
SQL语句
索引,Index
数据库结构
引擎特定的优化:InnoDB、MyISAM、Memory等引擎
查询执行计划
控制查询优化器
缓冲与缓存(Buffering and Caching)
锁优化
MySQL Server优化
性能测试,Measuring Performance(Benchmarking)
线程信息检查,Examining ThreadInformation
77、关于优化SQL Statements
SQL语句,从使用目的上可分为两种类型:1、数据处理;2、系统监控。因此,SQL优化也从这两种目的上分别进行。
SQL 语句的优化包括很多范围,大致如下:
优化Select语句
优化子查询、派生表、视图引用、公用表表达式
优化Information Schema查询
优化Performance Schema查询
优化数据变更语句(insert、update、delete)
优化数据库权限
还有其他一些小地方【略】
78、关于Select优化
看看标题,不详述了:
79、关于Where优化
一句话,去掉没用的条件;优化条件。
早期检查常数表达式
如果没有分组函数和Group By,Having与where合并。
构造简单的Where条件,以便获得快速Where评估。并尽可能多的过滤掉行。
固定表格(no row或只有1行的表;主键匹配)优先加载。
如果order和group都来自一个表,这个表最好能作为join的第一个
Order和group不一样,或Order来自不同的表,那会导致创建临时表。
80、关于Limit 查询优化
【不详细说了,看原文吧,上面有类似内容】
分为两部分:
需要分页时,考虑如何优化limit。Limit作为优化对象。
进行一些查询时(如order by),可以考虑用limit去优化它们。Limit作为优化手段。
81、重点看看InnoDB的大量数据加载问题:Bulk Data Loading for InnoDB Tables
这跟Insert大量数据的优化有关,考虑一下操作:
关闭自动提交,否则导致更频繁的flush log。
如果有Secondary唯一索引,先关闭唯一性检查。
如果有外键,先关闭外键检查。对大表来说,可节省超多的IO。
使用多行插入Insert into yourtable values (,,),(,,),…。
如果有自增列,可把innodb_autoinc_lock_mode设置为2
按照主键的顺序插入
82、关于InnoDB的若干优化
表格存储布局优化:考虑使用optimize table来重组表格;尽可能缩短主键长度;如果varchar太长考虑使用前缀索引;不固定长度的字符串使用varchar替代char;大表考虑使用Compressed行格式,以及考虑使用全表扫描等。
事务管理优化:找到事务特性的性能开销与工作负载的平衡点。Autocommit设置对日志刷新和只读事务的影响;避免大数据操作后的回滚,会恶化性能;事务日志的刷新机制;
只读事务优化:对只读事务避免设置事务ID而产生的开销。系统内有与优化机制。
Redo日志优化:太小会导致不必要的写磁盘,最新版本下,大的Redo文件不会导致太长时间的恢复,已经优化了。如果有大事务,要把缓冲区设置的大一些。
大量数据加载优化:尤其是批量insert场景下,进行特定的设置。
查询优化:关键是对index的创建和使用。
DDL操作优化:比如使用truncate table,如果有外键可先drop table再create。
磁盘I/O优化:通常的缓存设置;日志刷新机制等;使用Linux native AIO等等;利用多个磁盘;
配置优化:很多配置项优化
多表的系统优化:【看原文吧】
83、InnoDB的锁
共享锁和排它锁(Shared and Exclusive Locks):InnoDB实现了标准的行级锁,包括有两种类型:共享锁(S锁)和排它锁(X锁)。
意向锁(Intention Locks):InnoDB支持多种粒度锁共存,行级锁和表级锁,比如使用Lock table write锁定表。为了提供多种粒度级别上进行实际锁定,InnoDB使用意向锁(Intention Lock)。意向锁是表级锁,用于指示事务稍后对于表中的行需要哪种类型的锁(共享或独占)。意向共享锁(IS)(Select for share)表示事务意图获取表的每行共享锁。意向排它锁(IX)(Select for update)表示事务意图获取表的每行排它锁。
记录锁(Record Locks):对索引记录进行加锁,即使一个表没有定义索引,InnoDB引擎也会创建一个隐藏的聚簇索引。
间隙锁(Gap Locks):索引记录之间的“间隙”进行加锁,或者是第一个记录之前,或者是最后一个记录之后的“间隙”。所谓间隙,有可能有1个值或多个值,也可能是空。
下一主键锁(Next-Key Locks):记录锁和间隙锁的组合。
插入意向锁(Insert Intention Locks):是间隙锁的一种,多个事务对同一间隙序列进行插入时需要等待。
自增锁(AUTO-INC Locks):表级锁,这个innodb_autoinc_lock_mode配置对自增机制有影响。
空间索引的断言锁(Predicate Locks for Spatial Indexes):【略】