一、存储引擎
1、InnoDB
⑴InnoDB是基于聚簇索引建立的,基于主键索引查询时,性能较好;它的辅助索引中必须包含主键列;因此,若表上的索引较多,为节约空间,主键应尽可能小
⑵InnoDB支持自适应hash索引、事务、行级锁、热备份,采用MVCC支持高并发;不支持全文索引
⑶表存储格式:
①将所有innodb表的数据放置同一个表空间中;
表结构定义:tb_name.frm (数据库目录下)
数据和索引:统一的表空间文件中,默认路径是数据目录下ibdata#
innodb_data_file_path:表空间文件的文件名称及特性
可使用相对(相对于innodb_data_home_dir而言)或绝对路径,且可定义多个文件;
例:innodb_data_file_path = ibdata1:20G;ibdata2:10G;ibdata3:1G:autoextend
innodb_data_home_dir:表空间文件的存储位置,省略时表示使用数据目录(datadir变量定义的位置);
②每张表使用单独表空间;MariaDB中已默认启用此存储格式
表结构定义:tb_name.frm
数据和索引:tb_name.ibd
SET {GLOBAL|SESSION} innodb_file_per_table = 'on';
优点:迁移或备份数据更精细灵活
缺点:DROP TABLE操作的性能较差
⑷InnoDB缓冲池:buffer pool,由InnoDB维护的内存空间,用于缓存索引及数据;缓冲池如果太大,预热会比较慢。
innodb_buffer_pool_size
⑸查看InnoDB存储引擎的状态:SHOW ENGINE INNODB STATUS;
2、MyISAM
⑴MySQL 5.5.5之前的默认引擎
支持全文索引、压缩、空间函数;
不支持外键约束
不支持事务、行级锁、热备份;
读写互相阻塞
崩溃后无法安全恢复;
支持延迟更新索引键(delay_key_write):每次修改表后,修改的索引数据不会立即写入磁盘,而是写入内存的键缓冲区,只有当清理键缓冲区或关闭表时才会写入磁盘,这样提高了写性能,但数据库崩溃时,易造成索引损坏。
MyISAM可以通过 key_buffer_size 缓存索引键,但此缓存只会缓存索引,不会缓存数据
读取数据快,占用资源相对少
⑵表存储格式:每张表都有三个文件(位于数据库目录下)
tb_name.frm:表格式
tb_name.MYD:数据
tb_name.MYI:索引
3、其它存储引擎
Memory:早期叫HEAP表,将数据放在内存中,因此访问速度快,但无法持久存储数据,显式支持hash索引。
CSV:将数据存储为文本文件,字段以逗号分隔;不支持索引,常用于数据交换的场景。
Merge:MyISAM的变种,将多个MyISAM表合并表示为一个虚拟表;
Federated:访问其它MySQL服务上数据的代理;MariaDB上用的是FederatedX
Blackhole:没有任何存储机制,所以会丢弃所有的插入的数据;
NDB:Cluster:mysql集群的存储引擎
第三方存储引擎:
OLTP类:
XtraDB:InnoDB的改进版
PBXT:支持ACID和MVCC
TokuDB:支持使用分形树的索引结构,适用存储大数据
面向列的存储的引擎:按列为单位进行存储,适合压缩等,适用于存储大数据
Infobright, InfiniDB, LucidDB
社区引擎:
Aria:MyISAM的改进版,支持崩溃后安全恢复
OQGraph:支持图操作
SphinxSE:为sphinx全文搜索引擎提供了SQL接口;
Spider:可以将数据切分成不同的分区,较透明实现分片功能;
4、查看默认存储引擎:
show global variables like '%storage_engine';
mysql 5.5之后默认存储引擎为innodb
5、存储引擎的选择
选择标准:是否支持事务,热备份,崩溃后恢复等
数据仓库建议使用MyISAM或Aria,在线事务处理建议使用InnoDB
MariaDB [testdb]> show engines;+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+| Engine | Support | Comment | Transactions | XA | Savepoints |+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+| PERFORMANCE_SCHEMA | YES | Performance Schema | NO | NO | NO || CSV | YES | CSV storage engine | NO | NO | NO || MRG_MyISAM | YES | Collection of identical MyISAM tables | NO | NO | NO || BLACKHOLE | YES | /dev/null storage engine (anything you write to it disappears) | NO | NO | NO || MEMORY | YES | Hash based, stored in memory, useful for temporary tables | NO | NO | NO || Aria | YES | Crash-safe tables with MyISAM heritage | NO | NO | NO || ARCHIVE | YES | Archive storage engine | NO | NO | NO || MyISAM | YES | MyISAM storage engine | NO | NO | NO || InnoDB | DEFAULT | Percona-XtraDB, Supports transactions, row-level locking, and foreign keys | YES | YES | YES |+--------------------+---------+----------------------------------------------------------------------------+--------------+------+------------+9 rows in set (0.04 sec)MariaDB [(none)]> show global variables like '%storage_engine';+------------------------+--------+| Variable_name | Value |+------------------------+--------+| default_storage_engine | InnoDB || storage_engine | InnoDB |+------------------------+--------+2 rows in set (0.00 sec)MariaDB [(none)]> select @@global.innodb_file_per_table;+--------------------------------+| @@global.innodb_file_per_table |+--------------------------------+| 1 |+--------------------------------+1 row in set (0.00 sec)MariaDB [(none)]> \! ls /mydata/dataaria_log.00000001 hellodb ib_logfile0 multi-master.info mysql-bin.000001 mysql-bin.000003 mysql-bin.000005 node1.err performance_schema testdbaria_log_control ibdata1 ib_logfile1 mysql mysql-bin.000002 mysql-bin.000004 mysql-bin.index node1.pid testMariaDB [(none)]> \! ls /mydata/data/testdbdb.opt students.frm students.ibd wuxia.frm wuxia.ibd
二、查询缓存
⑴查询的执行流程:
SELECT→[QUERY CACHE(查询缓存)→]PARSER(解析器)→OPTIMIZER(优化器)→EXECUTING ENGINE(执行引擎)→STORAGE ENGINE
开启MySQL查询缓存功能后,查询缓存会保存查询返回的完整结果,当查询命中该缓存,MySQL会立刻返回结果,而跳过分析、优化和执行阶段。
⑵缓存的内容是key-value格式
key:查询语句的hash码
value:查询语句的执行结果
⑶查询缓存的优缺点:
优点:当查询命中缓存时,就能直接返回结果,跳过了后续一系列繁琐的过程,因此速度大大提升
缺点:因为要跟缓存中的键比对,因此,当查询未命中缓存时,实际上是给整个查询过程增加了一项开销;此外,当并发量较大时,缓存成了资源争用点,有可能成为性能瓶颈。
⑷什么样的语句不会缓存?
查询语句中有不确定数据时不会缓存,比如current_time();
一般来说,如果查询中包含用户自定义的函数、存储函数、用户变量、临时表、mysql库中表、或者任何包含权限信息表,都不会缓存;
⑸缓存什么场景下会比较有效?
对于需要牵扯大量资源的查询非常适合启用缓存;
不适宜数据更新频繁的场景,因为那样缓存失效很快
⑹与缓存功能相关的服务器变量:
SHOW GLOBAL VARIABLES LIKE 'query_cache%';
query_cache_limit: MySQL能够缓存的最大查询结果;如果某查询的结果大于此值,则不会被缓存;
query_cache_min_res_unit: 查询缓存中分配内存的最小单位;
计算公式:(query_cache_size-Qcache_free_memory)/Qcache_queries_in_cache,即(总空间-剩余空间)/查询的个数
query_cache_size: 查询缓存的总体可用空间;其必须为1024的倍数,0表示关闭缓存
query_cache_type: ON, OFF, DEMAND
DEMAND:按需进行缓存,意思是只有明确写明要缓存的SELECT语句的结果才会进行缓存; SQL_CACHE | SQL_NO_CACHE
query_cache_wlock_invalidate:当其它会话锁定此次查询的资源时,是否不能再从缓存中返回数据;
⑺与缓存相关的状态变量:
SHOW GLOBAL STATUS LIKE 'Qcache%';
Qcache_free_blocks
Qcache_free_memory
Qcache_hits: 缓存命中的次数
Qcache_inserts: 插入的缓存的个数
Qcache_lowmem_prunes: 由于可用缓存空间过低导致清理缓存的次数
Qcache_not_cached
Qcache_queries_in_cache: 仍留在缓存空间中的缓存的个数
Qcache_total_blocks
⑻衡量缓存的有效性:命中率, hit/(hit+miss)
常以 Qcache_hits/Com_select 的值作为参考
另外,也可参考 Qcache_hits/Qcache_inserts。如果此比值大于3:1, 说明缓存也是有效的;如果高于10:1,相当理想;
⑼缓存优化的思路:
①批量写入比单次写入对缓存的影响要小得多;
②缓存空间不宜过大,大量缓存的同时失效会导致MySQL假死;
③必要时,使用SQL_CACHE或SQL_NO_CACHE手动控制缓存;
④对写密集型的应用场景,禁用缓存反而能提高性能;
⑽碎片整理:FLUSH QUERY CACHE;
⑾清空缓存:RESET QUERY CACHE;
MariaDB [(none)]> show global variables like 'query_cache%';+------------------------------+----------+| Variable_name | Value |+------------------------------+----------+| query_cache_limit | 1048576 || query_cache_min_res_unit | 4096 || query_cache_size | 16777216 || query_cache_strip_comments | OFF || query_cache_type | ON || query_cache_wlock_invalidate | OFF |+------------------------------+----------+6 rows in set (0.00 sec)MariaDB [testdb]> show global status like 'Qcache%';+-------------------------+----------+| Variable_name | Value |+-------------------------+----------+| Qcache_free_blocks | 1 || Qcache_free_memory | 16757096 || Qcache_hits | 8 | #命中8次| Qcache_inserts | 41 || Qcache_lowmem_prunes | 0 || Qcache_not_cached | 65 || Qcache_queries_in_cache | 2 | #缓存中仍有两个条目| Qcache_total_blocks | 6 |+-------------------------+----------+8 rows in set (0.00 sec)MariaDB [testdb]> reset query cache; #清空查询缓存Query OK, 0 rows affected (0.00 sec)MariaDB [testdb]> show global status like 'Qcache%';+-------------------------+----------+| Variable_name | Value |+-------------------------+----------+| Qcache_free_blocks | 1 || Qcache_free_memory | 16759656 || Qcache_hits | 8 || Qcache_inserts | 41 || Qcache_lowmem_prunes | 0 || Qcache_not_cached | 65 || Qcache_queries_in_cache | 0 | #缓存中已没有条目| Qcache_total_blocks | 1 |+-------------------------+----------+8 rows in set (0.00 sec)