mysql的存储引擎是针对表进行设置的,一个库的不同表可以设置不同的存储引擎,mysql默认支持多种存储引擎,以适用不同领域的数据库应用需要,主要的几个数据库引擎如下:
5.5之前默认的存储引擎,不支持事务、不支持外键,表级锁,内存和硬盘空间占用率低,其优势是访问速度快,对事务完整性没有要求,以select、insert为主的应用基本上都可以使用这个引擎;
5.5之后默认的存储引擎,提供了具有提交、回滚和奔溃恢复能力的事务安全,支持外键并提供了行级锁,其劣势在于写的处理效率相对较低,并且会占用更多的磁盘空间以保留数据和索引;
使用存于内存中的内容来创建表,MEMORY类型的表数据存于内存访问非常的快,默认使用HASH索引,一旦数据库服务重启或关闭,表中的数据就会丢失;
MERGE存储引擎是一组MyISAM表组合,这些MyISAM表结构完全相同。MERGE表本身没有数据,对MERGE表的CRUD操作都是通过内部的MyISAM表进行的;
B-Tree 索引是 MySQL 数据库中使用最为频繁的索引类型, 除了 Archive 存储引擎之外的其他所有的存储引擎都支持 B-Tree 索引。不仅仅在 MySQL 中是如此,实际上在其他的 很多数据库管理系统中B-Tree 索引也同样是作为最主要的索 引类型,这主要是因为 B-Tree 索引的存储结构在数据库的 数据检 索中有非常优异的表现。
Hash 索引结构的特殊性,其检索效率非常高,索引的检索可 以一次定位,不像B-Tree 索引需要从根节点到枝节点,最后 才能访问到页节点这样多次的IO访问,所以 Hash 索引的查 询效率要远高于 B-Tree 索引。 但是hash索引不常用,因为hash索引没有默认排序。
普通索引: 最基本的索引,没有任何限制。
唯一索引: 与"普通索引"类似,不同的就是:索引列的值必须唯一,但允许有空值。
主键索引: 它是一种特殊的唯一索引,不允许有空值。
全文索引: 仅可用于 MyISAM 表,针对较大的数据,生成全文索引很耗时好空间。
组合索引: 为了更多的提高mysql效率可建立组合索引,遵循”最左前缀“原则。
补充:
聚簇索引(Clustered Indexes)
聚簇索引保证关键字的值相近的元组存储的物理位置也相同(所以字符串类型不宜建 立聚簇索引,特别是随机字符串,会使得系统进行大量的移动操作),且一个表只能 有一个聚簇索引。因为由存储引擎实现索引,所以,并不是所有的引擎都支持聚簇索 引。目前,只有solidDB和InnoDB支持。
非聚簇索引
二级索引叶子节点保存的不是指行的物理位置的指针,而是行的主键值。这意味着通 过二级索引查找行。
InnoDB对主键建立聚簇索引。如果你不指定主键,InnoDB会用一个具有唯一且非空值 的索引来代替。如果不存在这样的索引,InnoDB会定义一个隐藏的主键,然后对其建 立聚簇索引。一般来说,DBMS都会以聚簇索引的形式来存储实际的数据,它是其它二 级索引的基础。
关于 窄索引 和 宽索引
三星索引
sql查询过程:
优化目标:
sql语句的优化可以从以下几种情况考虑:
大批量数据插入空表
可将表设置成为MyISAM,并通过disable keys将唯一索引关闭;
大批量数据插入非空Innodb表,可采取如下措施提高效率:
sql优化的大部分内容说的都是查询优化,而查询优化和索引是分不开的。
Union all
来代替 or
。例如:select * from user where loginname="xxx" or telephone="xxxx"
不走索引,应该换成 select * from user where loginname="xxx" union all select * from user where telephone="xxx"
Select * from fentrust e limit 4100000, 10
换成 Select * from fentrust e Inner join (select fid from fentrust limit 4100000, 10) a on a.fid = e.fid
效率就高得多。在优化查询sql的时候特别要熟悉那些情况会导致不走索引,归纳总结如下:
select * from fuser where floginname='xxx' or femail='xx' or fstatus=1
SELECT * FROM ` fuser ` WHERE ` floginname ` LIKE "%7488%"
不走索引 – 正则表达式不使用索引,这应该很好理解,所以为什么在SQL中很难看到regexp关键字的原因 – 字符串与数字比较不使用索引;
SELECT * FROM ` fuser` WHERE `floginname` LIKE‘138%' -- 走索引
如:select id from t where num in(1,2,3)
换成
select id from t where num between 1 and 3
SELECT ` famount ` FROM ` fentrust ` WHERE ` famount `+10=30;-- 不会使用索引,因为所有索引列参与了计算
SELECT `famount` FROM `fentrust` WHERE LEFT(`fcreateTime`,4) <1990; -- 不会使用索引,因为使用了函数运算,原理与上面相同
很多时候用 exists 代替 in 是一个好的选择: select num from a where num in(select num from b)
,用下面的语句替换:
select num from a where exists(select 1 from b where num=a.num)
基础表维护时,系统要同时维护索引,不合理的索引将严重影响系统资源(主要表现在CPU和I/O上);插入、更新、删除数据产生大量db file sequential read锁等待,所以我们只有在必要的时候才建立索引。例如在表数据较大时,作为查询条件和排序字段的列就可以考虑建立索引。
以下是不适合建立索引的情况:
MySQL为我们提供了explain命令来分析sql语句的执行效率,通过explain命令获取mysql如何执行select语句的信息,包括在select语句执行过程中表如何连接和连接的顺序;
下面开始explain分析后的结果解析
下面对一些重要属性做详细介绍
1、SIMPLE,简单查询
2、PRIMARY,主查询(多个表关联时)
3、UNION,联合查询
4、DEPENDENT UNION,子查询中的联合查询
5、UNION RESULT,联合的结果集
6、SUBQUERY,第一个子查询
7、 DEPENDENT SUBQUERY,子查询中第一句
8、DERIVED,派生表
1、system
const联接类型的一个特例。表仅有一行满足条件
2、const
表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!
3、eq_ref
对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY。
eq_ref可以用于使用= 操作符比较的带索引的列。比较值可以为常量或一个使用在该表前面所读取的表的列的表达式。
4、.ref
对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。
ref可以用于使用=或<=>操作符的带索引的列。
5、 ref_or_null
该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。
6、index_merge
该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。
7、unique_subquery
该类型替换了下面形式的IN子查询的ref。value IN (SELECT primary_key FROM single_table WHERE some_expr)unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。
8、index_subquery
该联接类型类似于unique_subquery。可以替换IN子查询
9、range
只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL。
10、index
该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。
11、ALL
对于每个来自于先前的表的行组合,进行完整的表扫描。如果表是第一个没标记const的表,这通常不好,并且通常在它情况下很差。通常可以增加更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。
这个列可以显示的信息非常多,有几十种。常用如下:
(1).Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了
(2).Not exists
使用了反连接,先查询外表,再查询内表
(3).Range checked for each Record(index map:#)
没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行。这是使用索引的最慢的连接之一
(4).Using filesort
看到这个的时候,查询需要优化。MYSQL需要进行额外的步骤来发现如何对返回的行排序。它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行
(5).Using index
列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候
(6).Using temporary
看到这个的时候,查询需要优化。这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDER BY上,而不是GROUP BY上
(7).Using where
使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户。如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题
(8).firstmatch(tb_name):
5.6.x开始引入的优化子查询的新特性之一,常见于where字句含有in()类型的子查询。如果内表的数据量比较大,就可能出现这个.
(9).loosescan(m…n):
5.6.x之后引入的优化子查询的新特性之一,在in()类型的子查询中,子查询返回的可能有重复记录时,就可能出现这个
原则:写入频繁的数据库,不要开查询缓存。
缓存配置项:
query_cache_size:
Query_cache里的数据又怎么处理呢?首先要把Query_cache和该表 相关的语句全部置为失效,然后在写入更新。那么如果Query_cache
非常大,该表的查询结构又比较多,查询语句失效也慢,一个更新或 是Insert就会很慢,这样看到的就是Update或是Insert怎么这么慢了。 所以在数据库写入量或是更新量也比较大的系统,该参数不适合分配 过大。而且在高并发,写入量大的系统,建议把该功能禁掉。
query_cache_limit:
指定单个查询能够使用的缓冲区大小,缺省为1M。
query_cache_min_res_unit:
默认是4KB,设置值大对大数据查询有好处,但如果你的查询都是小 数据查询,就容易造成内存碎片和浪费。
sort_buffer_size = 2M
connection级参数。太大将导致在连接数增高时,内存不足。
max_allowed_packet = 32M
网络传输中一次消息传输量的最大值。系统默认值 为1MB,最大值是1GB,必须设置1024的倍数。
join_buffer_size = 2M
和sort_buffer_size一样,该参数对应的分配内存也是每个连接独享
tmp_table_size = 256M
默认大小是 32M。GROUP BY 多不多的问题
max_heap_table_size = 256M
key_buffer_size = 2048M
索引的缓冲区大小,对于内存在4GB左右的服务器来说,该参数可设 置为256MB或384MB。
read_buffer_size = 1M
read_rnd_buffer_size = 16M
进行排序查询时,MySql会首先扫描一遍该缓冲,以避免磁盘搜索
bulk_insert_buffer_size = 64M
批量插入数据缓存大小,可以有效提高插入效率,默认为8M
innodb_buffer_pool_size = 2048M
只需要用Innodb的话则可以设置它高达 70-80% 的 可用内存。一些应用于 key_buffer 的规则有 — 如 果你的数据量不大,并且不会暴增,那么无需把innodb_buffer_pool_size 设置的太大了。
innodb_additional_mem_pool_size = 16M
网络传输中一次消息传输量的最大值。系统默认值 为1MB,最大值是1GB,必须设置1024的倍数。
innodb_log_files_in_group = 3
循环方式将日志文件写到多个文件。推荐设置为3
innodb_lock_wait_timeout = 120
InnoDB 有其内置的死锁检测机制,能导致未完成 的事务回滚。
innodb_file_per_table = 0
独享表空间,关闭
open_files_limit = 10240
允许打开的文件数
back_log = 600
短时间内的多少个请求可以被存在堆栈中
max_connections = 3000
MySQL允许最大的进程连接数,MySQL默认的最大连接数为100,MySQL服务器允许的最大连接数16384
max_connect_errors = 6000
设置每个主机的连接请求异常中断的最大次数,当超过该次数,MYSQL服务器将禁止host的连接请求
thread_cache_size = 300
重新利用保存在缓存中线程的数量
thread_concurrency = 8
thread_concurrency应设为总CPU核数的2倍
thread_stack = 192K
每个线程的堆栈大小,默认值足够大,可满足普通操作。可设置范围为128K至4GB,默认为192KB。
thread_handling
表示线程池模型。
thread_pool_size
表示线程池的group个数,一般设置为当前CPU核心数目。理想情况下,一个group一个活跃的工 作线程,达到充分利用CPU的目的。
thread_pool_stall_limit
用于timer线程定期检查group是否“停滞”,参数表示检测的间隔。
thread_pool_idle_timeout
当一个worker空闲一段时间后会自动退出,保证线程池中的工作线程在满足请求的情况下,保持 比较低的水平。60秒
thread_pool_oversubscribe
该参数用于控制CPU核心上“超频”的线程数。这个参数设置值不含listen线程计数。
threadpool_high_prio_mode
表示优先队列的模式。
thread_pool_max_threads
限制线程池最大的线程数,超过将无法再创建更多的线程,默认为100000。
thread_pool_high_prio_tickets
最多语序多少次被放入高优先级队列中,默认为4294967295。 只有在thread_pool_high_prio_mode为transactions的时候才有效果
slow_query_log
是否开启慢查询日志,1表示开启,0表示关闭。
log-slow-queries
旧版(5.6以下版本)MySQL数据库慢查询日志存储路径。可以不设置该参数,系统则会默认给一个缺省 的文件host_name-slow.log
slow-query-log-file
新版(5.6及以上版本)MySQL数据库慢查询日志存储路径。可以不设置该参数,系统则会默认给一个缺 省的文件host_name-slow.log
long_query_time
慢查询阈值,当查询时间多于设定的阈值时,记录日志。
log_queries_not_using_indexes
未使用索引的查询也被记录到慢查询日志中(可选项)。
log_output
日志存储方式。log_output=‘FILE’表示将日志存入文件,默认值是’FILE’。log_output='TABLE’表示将日志 存入数据库,这样日志信息就会被写入到mysql.slow_log表中。MySQL数据库支持同时两种日志存储方式 ,配置的时候以逗号隔开即可,如:log_output=‘FILE,TABLE’。日志记录到系统的专用日志表中,要比记 录到文件耗费更多的系统资源,因此对于需要启用慢查询日志,又需要能够获得更高的系统性能,那么建 议优先记录到文件。
log-bin=mysql-bin
[必须]启用二进制日志
server-id=222
[必须]服务器唯一ID,默认是1,一般取IP最后一段
binlog-do-db=DB1
binlog-do-db=DB2 #如果备份多个数据库,重复设置这个选项即可
binlog-do-db=DB3 #需要同步的数据库,如果没有本行,即表示同步所有的数据库
binlog-ignore-db=mysql #被忽略的数据库
rpl_semi_sync_slave_enabled =1 #启用半同步复制
rpl_semi_sync_master_timeout=milliseconds
设置此参数值(ms),为了防止半同步复制在没有收到确认的情况下发生堵塞,如果Master在超时之前没有收到任何确认 ,将恢复到正常的异步复制,并继续执行没有半同步的复制操作。
rpl_semi_sync_master_wait_no_slave={ON|OFF}
如果一个事务被提交,但Master没有任何Slave的连接。默认情况下,Master会在时间限制范围内继续等待Slave的连接,并 确认该事务已经被正确的写到磁盘上。可以使用此参数选项关闭这种行为,在这种情况下,如果没有Slave连接,Master就 会恢复到异步复制。
master
GRANT REPLICATION SLAVE ON . to ‘mysync’@’%’ identified by ‘q123456’; //一般不用root帐号,“%”表示所有客户端都 可能连,只要帐号,密码正确,此处可用具体客户端IP代替,如192.168.145.226,加强安全。
slave
change master to master_host=‘192.168.145.222’,master_user=‘mysync’,master_password=‘q123456’,
master_log_file=‘mysql-bin.000004’,master_log_pos=308;
补充;
为了方便排查错误和使服务器的效率更高,我们可以安装服务器监控工具,相关的工具有innotop、天兔、PHPadmin等。