MyISAM索引优化
查看索引:
mysql> show index from squid \G;
建立索引:
mysql> create index ipidx on squid(ip);
mysql> alter table squid add index(url(32)); <--仅仅对url列前32个字符建立索引
查看执行计划
mysql> explain select * from squid where ip='10.1.1.22' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: squid
type: ref
possible_keys: ipidx
key: ipidx
key_len: 48
ref: const
rows: 1
Extra: Using where
不使用索引
mysql> explain select * from squid where url='http://www.baidu.com' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: squid
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 3360077
Extra: Using where
后缀模糊搜索不使用索引
mysql> explain select * from squid where url like '%baidu.com' \G;
*************************** 1. row ***************************
id: 1
select_type: SIMPLE
table: squid
type: ALL
possible_keys: NULL
key: NULL
key_len: NULL
ref: NULL
rows: 3360077
Extra: Using where
mysql> show variables like 'key_%';
+--------------------------+---------+
| Variable_name | Value |
+--------------------------+---------+
| key_buffer_size | 8384512 |
| key_cache_age_threshold | 300 |
| key_cache_block_size | 1024 |
| key_cache_division_limit | 100 |
+--------------------------+---------+
key_buffer_size 使用多少内存空间缓存索引文家的数据
key_cache_division_limit
key_buffer可以分为:hot_area和warm_area。100代表使用全部key_buffer空间作为warm_area,相当于不去区分哪些热点数据哪些冷数据。
key_cache_age_threshold
数值越少,热点数据越容易降级为冷点数据。
mysql> show status like 'key%';
+------------------------+----------+
| Variable_name | Value |
+------------------------+----------+
| Key_blocks_not_flushed | 0 |
| Key_blocks_unused | 7139 | 未使用多少BLOCK
| Key_blocks_used | 7245 | 使用了多少BLOCK
| Key_read_requests | 26308131 | 有多少个读请求直接在key_buffer中命中
| Key_reads | 126 | 有多少个读请求没有被命中,需要把.MYI加载到内存
| Key_write_requests | 6872188 | 写请求命中
| Key_writes | 67452 | 写请求未命中
+------------------------+----------+
key_buffer的读命中率 = Key_read_requests / ( Key_reads + Key_read_requests) * 100
key_buffer空间使用百分比 = Key_blocks_used / (Key_blocks_unused + Key_blocks_used )
自定义索引缓存。
使用多个key_cache.每个key_cache大小和用途有管理员决定。
建议建立三种key_cache:
Hot cache 使用20%
Cold cache 使用20% <--专用
Warm cache 使用60%
以上所有的空间都是来自于key_buffer
mysql> set global key_buffer_size=20*1024*1024;
设定多个key_cache区域
mysql> set global hot_cache.key_buffer_size=4*1024*1024;
mysql> set global cold_cache.key_buffer_size=4*1024*1024;
mysql> select @@hot_cache.key_buffer_size;
指定这些key_cache的专有用途
mysql> cache index log.squid in hot_cache;
mysql> cache index bbs.pw_nav in cold_cache;
手工加载这些索引数据到cache中
mysql> load index into cache log.squid ; 如果cache足够大,可以把整个索引放进去,那么就不需要ignore leaves
mysql> load index into cache bbs.pw_nav ignore leaves;
把多个表同时放入到一个cache
CACHE INDEX t1, t2, t3 IN hot_cache;
=======================================================
Innodb优化
Innodb是一个支持事务的存储引擎
事务的特性ACID:
原子性 atomicity:一直事务要么完全执行,要么就完全不执行。
一致性 consistency:让数据库始终保持数据一致的状态。
部门表,员工表
小明,小红是属于部门A,现在需要把部门A从部门表中删除。但删除之前,必须把所有属于部门A的员工记录删除,然后才能删除部门A。
隔离性 isolation:事务与事务之间是隔离执行,之间的影响是最小化,这样做是为了保证数据库是可以并发操作。
持久性 durability:完全执行的事务(提交的事务),影响的数据应该永久生效。
事务的并发控制
为了增大数据库的吞吐量,必须支持事务,而事务并发性必定会影响到事务的特性。会产生一下问题:
1、脏读问题
当一个事务读取被另外一个事务修改了但为提交的数据。
2、幻读问题
同一个事务,前后两次进行相同的查询,第二次查询的结果比第一次多了一些新的记录。原因:正在进行某个事务的时候,由于别的事务新添加了一些记录导致。
3、更新丢失
两个事务同时操作某条记录。事务A刚提交,事务B又提交,事务B把事务A的更新数据覆盖了。就称A事务更新丢失
4、不可重复读
重读读取记录,发现记录的数据已经被改变,就称这样的记录是不能重复度。
在通过一个事务,查询同一条记录多次,每次的结果都不一样,说明该记录被别的事务修改了,这样的记录就是不能重读读。
事务隔离:
事务隔离就是为了在事务并发的情况下保证事务不会相互干扰,数据是保持一致。
隔离级别:
未提交读:
允许事务读取其他事务未提交的数据。不能解决上面四个事务带来的问题
提交读:
只能查询到事务提交了的数据。oracle就是该级别。
可重复读:
在通过一个事务,查询相同的记录得到结果保证不变,开始是怎样,事务过程中,还是这个样。Innodb就是该级别。该解别解决了:脏读问题,不可重复读。标准的不可重复读是不会解决欢读的,只有innodb解决幻度问题。
串行级别:
该级别非常严格,所有事务都是串行执行。一个事务正在访问修改某个表的记录,那么这个事务会锁定整个表,不允许其他事务去访问,直到该事务结束。
新事务是从上一个事务结束后才开始
事务可以通过commit(提交)或者rollback(回滚)标记事务结束,或者执行来的DDL操作(create,alter...)
脏读 不可重复 幻读
未提交读 允许 允许 允许
提交读 允许 允许
可重复 允许(innodb出外)
串行
备注:允许,代表该级别会出现这些问题。
Innodb的设置参数:
mysql> show variables like 'inno%';
innodb文件的优化
数据文件:记录数据和索引数据
innodb_data_file_path=ibdata1:512M:autoextend
对于海量数据库,并发比较高,短期内会有大量数据更新,或者增加大量数据的,应该把值调整大一些。
日志文件:记录对innodb表的数据操作。日志文件是可以重复使用。日志文件的作用:保证数据库的数据是一致,必要时候可以根据日志对数据进行自动恢复。
innodb_log_file_size=1024M
innodb_log_files_in_group=3
innodb_open_files=1024 ## 还要保证open_files_limit比该值大
## table_open_cache,table_definition_cache 比该值大
innodb_doublewrite
双写入:
事务被提交了,然后就会产生相应的innodb日志,这些日志记录事务的所有对数据产生变更的操作,紧接这innobd会把涉及到的数据在innodb_buffer_pool里进行操作(进行相应的变更)。当时机成熟了,就会把数据同步到磁盘上数据文件,这样才能保证提交后事务的数据变更能够持久化保存。
如果启用的doublewrite,那么首先会把变更的数据刷新表空间(多个数据文件组成)保留的区域,该区域是连续,IO效率提高。然后才紧接这把这些数据更新到数据文件中的具体块(位置)。这样做还能避免部分写入的问题。
部分写入的问题: 假如某个事务修改了16KB的数据,事务提交后,需要把数据同步到数据文件。如果没有使用双写入功能,当写入了8KB数据到数据文件,然后突然件系统断了。系统恢复之后,就很可能数据丢失,严重的时候无法通过日志文件恢复。
10克糖 和 5克盐 放到 汤了。
糖和盐先放到带有刻度的独立容器
innodb内存调优
innodb专用的缓冲区:保存这innodb表的数据,修改过或者刚读取进来的数据,或者经常读取的数据
innodb_buffer_pool_size
根据实际情况设定:
8G
保留 800M给系统用
当个连线线程的一些内存组件:
sort_buffer 2M
join_buffer 2M
thread_stack 2M
binlog_cache_size 2M
假设最高并发500 ,需要 500*8=4G
key_buffer 500M
query_cache 100M
系统剩下的内存= 8G - 5.4G = 2.6G
负载缓存区
innodb_additional_mem_pool_size
默认1M,一般调整为8M就绝对够用,就算不够用,mysql也会自动调整。
innodb_log_buffer_size
默认是1M,一般是2M-8M就够了。用户缓存日志记录的。当条件满足的时候,就会把缓冲区里日志记录刷到日志文件。建议2M就好了。
innodb_flush_log_at_trx_commit
影响到性能和日志记录安全的。
0 性能一般。每一秒钟就会把日志缓冲区里的数据刷到磁盘日志文件,而且保证是真正的写入了日志文件,不会出现文件系统缓存问题。mysqld进程crash掉了,最悲剧的情况就是丢失1秒钟的事务。
1 性能最差,但是是最安全的。每一次事务提交,都会把日志缓冲区里的记录刷新到磁盘文件,而且不会出现文件系统缓存问题。如果mysqld进程crash掉了,不会造成日记记录丢失,操作系统断掉也不会丢失数据。
2 性能好,但不安全。每一次事务提交,都会把日志缓冲区里的记录刷新到磁盘文件,但不保证数据被真正写入磁盘文件。如果mysql进程crash掉了,不会造成数据丢失。如果机器crash掉,会造成最后一次事务的数据丢失。
转载于:https://blog.51cto.com/linuxart/844044