MariaDB数据库存储引擎、索引和EXPLAINhtml
----------------------------------------------------------------------------------------------------------------------------------------mysql
MySQL5.5.5前默认的数据库引擎为MyISAM,以后的是InnoDB,如今新版本是InnoDB的增强版XtraDB数据库
MyISAM安全 |
InnoDB性能优化 |
|
最大存储服务器 |
256TBsession |
64TB并发 |
事务 |
N |
Y |
锁 |
表锁 |
行锁 |
MVCC |
N |
Y |
B-TREE |
Y |
Y |
全文索引 |
N |
Y |
聚簇索引 |
N |
Y |
数据缓存 |
N |
Y |
索引缓存 |
Y |
Y |
<1>事务:多种操做的集合。多会话访问数据库时,每个操做都会有一个ID,之间互不干扰。假设A在数据库的某张表中有先插入、再删除的操做,操做同时B在查询这张表,那么B查询到的结果是A插入未删时的数据仍是A已经删除的操做?其实当A作插入insert操做时,数据库会自动给该动做分配一个ID,作删除的操做时候回再分配一个ID,且后面操做的ID大于签名操做的ID。若是B的查询操做ID位于A的插入以后,删除以前,那么B查询到的就是A在insert后的结果,delete以前的结果
Ainsert=10,Adelete=20,Bselect=15,此时B能够查到A在insert的结果,查询不到A的delete后的结果。
<2>锁:表锁:锁的动做是对整个表上锁,上锁后其余用户不得访问读写
<3>脏数据:事务过程当中尚未结束完的数据,好比说刚才说的A在insert和delete之间未完成的数据
<2>适用场景:只读(或者写较少)、表较小(能够接受长时间进行修复操做)
<5>InnoDB引擎下,建议修改/etc/my.cnf,在[mysqld]下添加defaults-storage-engine=INNODB和innodb-file-per-table,不然全部InnoDB表的数据和索引放置于同一个表空间中
设置好后今后以后新建的数据库都将数据文件和表格式定义分开存放
数据文件(存储数据和索引):tb_name.ibd,表格式定义:tb_name.frm
(1)Performance_Schema:Performance_Schema数据库
(2)Memory :将全部数据存储在RAM中,以便在须要快速查找参考和其余相似数据的环境中进行快速访问。适用存放临时数据。引擎之前被称为HEAP引擎
(3)MRG_MyISAM:使MySQL DBA或开发人员可以对一系列相同的MyISAM表进行逻辑分组,并将它们做为一个对象引用。适用于VLDB(Very Large Data Base)环境,如数据仓库
(4)Archive :为存储和检索大量不多参考的存档或安全审核信息,只支持SELECT和INSERT操做;支持行级锁和专用缓存区
(5)Federated联合:用于访问其它远程MySQL服务器一个代理,它经过建立一个到远程MySQL服务器的客户端链接,并将查询传输到远程服务器执行,然后完成数据存取,提供连接单独MySQL服务器的能力,以便从多个物理服务器建立一个逻辑数据库。很是适合分布式或数据集市环境
(6)BDB:可替代InnoDB的事务引擎,支持COMMIT、ROLLBACK和其余事务特性
(7)Cluster/NDB:MySQL的簇式数据库引擎,尤为适合于具备高性能查找要求的应用程序,这类查找需求还要求具备最高的正常工做时间和可用性
(8)CSV:CSV存储引擎使用逗号分隔值格式将数据存储在文本文件中。可使用CSV引擎以CSV格式导入和导出其余软件和应用程序之间的数据交换
(9)BLACKHOLE :黑洞存储引擎接受但不存储数据,检索老是返回一个空集。该功能可用于分布式数据库设计,数据自动复制,但不是本地存储
(10)example:“stub”引擎,它什么都不作。可使用此引擎建立表,但不能将数据存储在其中或从中检索。目的是做为例子来讲明如何开始编写新的存储引擎
三、MariaDB支持的其它存储引擎:OQGraph、SphinxSE、TokuDB、Cassandra、CONNECT、SQUENCE
Show table status from db_name;
show table status like ' tb_name';
CREATE TABLE tb_name(... ) ENGINE=InnoDB;
ALTER TABLE tb_nameENGINE=InnoDB;
(1)mysql数据库:mysql的核心数据库,相似于sql server中负责存储数据库的用户、权限设置、关键字等mysql本身须要使用的控制和管理信息
(2)performance_schema:mysql 5.5开始新怎的数据库,主要用于收集数据库服务器性能参数,库里表的存储引擎均为performance_schema,用户不能建立存储引擎为performance_schema的表
(3)information_schema数据库:mysql 5.0以后产生的,一个虚拟数据库,物理上并不存在。提供了访问数据库元数据的方式,即数据的数据。
(1)mysqld选项,服务器系统变量和服务器状态变量,在两个官方网址中查询是服务器变量仍是服务器选项
https://dev.mysql.com/doc/refman/5.7/en/mysqld-option-tables.html
https://mariadb.com/kb/en/library/full-list-of-mariadb-options-system-and-status-variables/
<1>在命令行中设置./mysqld_safe --skip-name-resolve=1;
<2>在配置文件my.cnf中添加skip_name_resolve=1,避免IP被反向解析为名字,建议添加此项
(6)修改全局变量:仅对修改后新建立的会话有效;对已经创建的会话无效
mysql> SET GLOBAL system_var_name=value;
mysql> SET @@global.system_var_name=value;
mysql> SET [SESSION] system_var_name=value;
mysql> SET @@[session.]system_var_name=value;
(8)状态变量(只读):用于保存mysqld运行中的统计数据的变量,不可更改
(1)有些既是服务器变量,又是服务器选项,好比说--binlog-cacho-size为选项,但也有binlog_cache_size的变量
(2)当修改变量时用SET [GLOBAL] VARNAME=value做为修改,用show variables like ' ';查询,该变量修改后会在重启后消失,并且变量不支持加入配置文件中。选项的修改能够直接将该选项放入/etc/my.cnf下的[mysqld],该修改成永久保存。查找是服务器变量仍是服务器选项去刚给的官网网址能够查找
(3)查询变量show [global] variables like '...%';
查询状态变量show [global] status like '...%';,不可更改,只读
(1)SQL_MODE:对其设置能够完成一些约束检查的工做,可分别进行全局的设置或者当前会话的设置
(2)开启方式:SET SQL_MODE='traditional',加上global对全局设置,不加global对当前会话设置
<1>NO_AUTO_CREATE_USER:禁止GRANT建立密码为空的用户
<2>NO_ZERO_DATE:在严格模式,不容许使用‘0000-00-00’的时间
<3>ONLY_FULL_GROUP_BY:对于GROUP BY分组操做,若是SELECT的字段没有在分组GROUP BY中存在会认为这个SQL语句是不合法的
<4>NO_BACKSLASH_ESCAPES:反斜杠\做为普通字符而非转义字符
<5>PIPES_AS_CONCAT:将||视为链接操做符而非“或运算符”
(1)查询先看是否有查询缓存,若是有将直接显示缓存,加快了速度。因为查询缓存运用了哈希运算,所以若是想要引用查询缓存,SQL语句使用须要与在查询缓存中的SQL语句如出一辙,甚至大小写一致
<2>查询语句中含有得到值的函数,包含自定义函数,如:NOW()
CURDATE()、GET_LOCK()、RAND()、CONVERT_TZ()等
<3>对系统数据库的查询:mysql、information_schema查询语句中使用SESSION级别变量或存储过程当中的局部变量
<4>查询语句中使用了LOCK IN SHARE MODE、FOR UPDATE的语句,查询语句中相似SELECT …INTO 导出数据的语句
<5>对临时表的查询操做;存在警告信息的查询语句;不涉及任何表或视图的查询语句;某用户只有列级别权限的查询语句
<6>事务隔离级别为Serializable时,全部查询语句都不能缓存
show variables like 'query_cache%';
<1>query_cache_min_res_unit: 查询缓存中内存块的最小分配单位,默认4k,较小值会减小浪费,但会致使更频繁的内存分配操做,较大值会带来浪费,会致使碎片过多,内存不足
<2>query_cache_limit:单个查询结果能缓存的最大值,默认为1M,对于查询结果过大而没法缓存的语句,建议使用SQL_NO_CACHE
<3>query_cache_size:查询缓存总共可用的内存空间;单位字节,必须是1024的整数倍,最小值40KB,低于此值有警报
<4>query_cache_wlock_invalidate:若是某表被其它的会话锁定,是否仍然能够从查询缓存中返回结果,默认值为OFF,表示能够在表被其它会话锁定的场景中继续从缓存返回数据;ON则表示不容许
<5>query_cache_type: 是否开启缓存功能,取值为ON, OFF, DEMAND,当query_cache_type的值为ON或1时,查询缓存功能打开,SELECT的结果符合缓存条件即会缓存,显式指定SQL_NO_CACHE,不予缓存,此为默认值;当query_cache_type的值为DEMAND或2时,查询缓存功能按需进行,显式指定SQL_CACHE的SELECT语句才会缓存;其它均不予缓存
注意:以上为服务器变量,设置时候是SET [GLOBAL] VARNAME=value;
查询变量或者选项示例:
查询缓存相关的状态变量:SHOW GLOBAL STATUS LIKE ‘Qcache%';
(1)Qcache_free_blocks:处于空闲状态Query Cache中内存Block 数
(2)Qcache_total_blocks:Query Cache 中总Block ,当Qcache_free_blocks相对此值较大时,可能用内存碎片,执行FLUSH QUERY CACHE清理碎片
(3)Qcache_free_memory:处于空闲状态的Query Cache 内存总量
(4)Qcache_hits:Query Cache 命中次数,好比输入同一个SQL查询语句两次,该记录会加1,两次输入的SQL语句大小必须一致
(5)Qcache_inserts:向Query Cache 中插入新的Query Cache 的次数,即没有命中的次数
(6)Qcache_lowmem_prunes:0记录有多少条查询由于内存不足而被移除出查询缓存
(7)Qcache_not_cached:没有被Cache 的SQL 数,包括没法被Cache 的SQL 以及因为query_cache_type设置的不会被Cache 的SQL语句,好比select now()输入后,该记录会加1
(8)Qcache_queries_in_cache:在Query Cache 中的SQL 数量
由此能够得出命中率和内存使用率估算:
(1)查询缓存中内存块的最小分配单位query_cache_min_res_unit:(query_cache_size-Qcache_free_memory) / Qcache_queries_in_cache
(2)查询缓存命中率:Qcache_hits/ ( Qcache_hits+ Qcache_inserts) * 100%
(3)查询缓存内存使用率:(query_cache_size–qcache_free_memory) / query_cache_size* 100%
(1)InnoDB存储引擎的缓冲池:一般InnoDB存储引擎缓冲池的命中不该该小于99%
show global status like 'innodb%read%'\G
<1>Innodb_buffer_pool_reads: 表示从物理磁盘读取页的次数
<2>Innodb_buffer_pool_read_ahead: 预读的次数
<3>Innodb_buffer_pool_read_ahead_evicted: 预读页,可是没有读取就从缓冲池中被替换的页数量,通常用来判断预读的效率
<4>Innodb_buffer_pool_read_requests: 从缓冲池中读取页次数
<6>Innodb_data_reads: 发起读取请求的次数,每次读取可能须要读取多个页
<1>占用额外空间,影响插入速度,不过对于具备大量查询需求的数据库是值得的
<1>B-TREE(念做B树)、B+ TREE、HASH、R TREE
<2>聚簇(集)索引、非聚簇索引:数据和索引是否存储在一块儿
全值匹配:精确全部索引列,如:姓wang,名xiaochun,年龄30
精确匹配某一列并范围匹配另外一列:如:姓wang,名以x开头的
如不从最左列开始,则没法使用索引,如:查找名为xiaochun,或姓为g结尾
不能跳过索引中的列:如:查找姓wang,年龄30的,只能使用索引第一列
若是查询中某个列是为范围查询,那么其右侧的列都没法再使用索引:如:姓wang,名x%,年龄30,只能利用姓和名上面的索引
为优化性能,可能须要针对相同的列但顺序不一样建立不一样的索引来知足不一样类型的查询需求
<1>Hash索引:基于哈希表实现,基于哈希表实现,只有精确匹配索引中的全部列的查询才有效,索引自身只存储索引列对应的哈希值和数据指针,索引结构紧凑,查询性能好
<2>Memory存储引擎支持显式hash索引,InnoDB和MyISAM存储引擎不支持
<3>适用场景:只支持等值比较查询,包括=, <=>, IN()
不支持部分索引列匹配查找:如A,B列索引,只查询A列索引无效
(9)地理空间索引( Geospatial indexing)
MyISAM支持地理空间索引,可使用任意维度组合查询,使用特有的函数访问,经常使用于作地理存储存储,使用很少
冗余索引:(A),(A,B),好比说有了idx_name_age创建的符合索引,此时再有name或者age的索引,name或者age就是冗余索引
<1>独立地使用列:尽可能避免其参与运算,独立的列指索引列不能是表达式的一部分,也不能是函数的参数,在where条件中,始终将索引列单独放在比较符号的一侧
<2>左前缀索引:构建指定索引字段的左侧的字符数,要经过索引选择性来评估,好比说某个表格name字段定义时候是CHAR(50),但name字段中的全部值按照CHAR(10)的规格就可使用,此时定义name索引时能够更改name字段字符数,CREATE INDEX idx_name ON tbl_name(name(10));
<3>多列索引:AND操做时更适合使用多列索引,而非为每一个列建立单独的索引,查询语句的where从句中用and链接两个加了索引的字段
<4>选择合适的索引列顺序:无排序和分组时,将选择性最高放左侧
CREATE INDEX index_name ON tbl_name (index_col_name[(length)],...);
SELECT ... WHERE 字符(加索引的字段) { like | in | = ...};
DROP INDEX index_name ON tbl_name;
SHOW INDEXES FROM [db_name.]tbl_name;
OPTIMIZE TABLE tb_name;,当索引创建后长时间不用
示例:现有一存储过程,能够实现创建99999个用户id、name、age的表格
以后mysql DB < FILE.sql,进入数据库调用call protestlog,产生数据表如图
利用索引查询和不利用索引查询
创建复合索引
(1)只要列中含有NULL值,就最好不要在此例设置索引,复合索引若是有NULL值,此列在使用时也不会使用索引
(4)对于有多个列where或者order by子句,应该创建复合索引
(5)对于like语句,以%或者‘-’开头的不会使用索引,以%结尾会使用索引,索引使用禁止使用like '%...'或者'%...%',只容许'...%'的形式
(3)多表链接时,尽可能小表驱动大表,即小表 join 大表
(5)type:关联类型或访问类型,即MySQL决定的如何去查询表中的行的方式,如下顺序,性能从低到高
<2>index:根据索引的次序进行全表扫描;若是在Extra列出现“Using index”表示了使用覆盖索引,而非全表扫描
<3>range:有范围限制的根据索引实现范围扫描;扫描位置始于索引中的某一点,结束于另外一点
<5>eq_ref:仅返回一个行,但与须要额外与某个参考值作比较
(9)ref: 在利用key字段所表示的索引完成查询时所用的列或某常量值
(10)rows:MySQL估计为找全部的目标行而须要读取的行数
Using index:MySQL将会使用覆盖索引,以免访问表
Using where:MySQL服务器将在存储引擎检索后,再进行一次过滤
Using temporary:MySQL对结果排序时会使用临时表
出现黄字状况possible_keys有值,但key为NULL