Submitted by admin on 2012, April 12, 6:07 PM
最近看了看mysql的状态变量,感觉好多跟以前自己想象的不一样。为了以后能及时发现自己的错误,就先记下来;
http://dev.mysql.com/doc/refman/5.1/en/server-status-variables.html
mysql> show status;
Binlog_cache_disk_use 0
Binlog_cache_use 5732727
Binlog_cache_use表示有多少个事物使用了binlog_cache_size来缓存未提交的事物日志。
Binlog_cache_disk_use 当事务日志比binlog_cache_size大时,他会创建临时文件,该状态表示有多少个事务使用了临时文件
以上两个参数可以用来动态调整binlog_cache_size变量,并且以上两个值只有在启动log-bin日志时才会有变化
Com_xxx 语句计数变量表示每个xxx 语句执行的次数。每类语句有一个状态变量。例如,Com_delete和Com_insert分别统计DELETE 和INSERT语句执行的次数。然而,如果一个查询的结果是从查询缓存中得到的,这会增加Qcache_hits,而不是Com_select
Connections 4192
试图连接到(不管是否成功)MySQL服务器的连接数。
Created_tmp_disk_tables 0
服务器执行语句时在硬盘上自动创建的临时表的数量
Created_tmp_files 5
mysqld创建的临时文件个数
Created_tmp_tables 1
服务器执行语句时在内存上自动创建的临时表的数量,如果Created_tmp_disk_tables较大,你可能要增加tmp_table_size值使临时 表基于内存而不基于硬盘。
Flush_commands 1
flush的执行个数
Handler_commit 0
Handler_delete 0
从 表中delete行的次数,此参数与 Com_delete不一样,只要执行delete,Com_delete就会增加,而Handler_delete只有当在表中删除了行的时候才增加。 如果delete删除没有影响到表里的任何行,则不会增加Handler_delete值
Handler_discover 0
Handler_prepare 0
Handler_read_first 0
索引中第一条被读的次数。这个表明。服务器正在进行全索引扫描 explain看的时候tpye类型为index
Handler_read_key 0
根据索引读行的次数,如果较高,说明查询使用了正确的表索引,explain看的时候tpye类型为const、eq_reg、ref、range、
Handler_read_next 0
根据键顺序来读取下一行,如果你使用索引范围(range)或执行索引(index)扫描,该值增加,增加的大小为查出来的行数,一般order by 键值 该值增加
Handler_read_prev 0
根据键顺序来读取前一行, 基本上是用在ORDER BY ... DESC. 增加的大小为查出来的行数
Handler_read_rnd 0
根据固定位置读一行的请求数,当需要对非键值排序时,该值会增加或者需要mysql扫描整个表时,该值会增加,增加的大小为查出来的行数
Handler_read_rnd_next 0
在数据文件中读下一行的请求数,如果你正进行大量的表扫描,该值较高,并且增加的值为扫描的行数
(select * from mrhao_order_info where address like '%AA%' order by address ,这个值会导致Handler_read_rn增加7,Handler_read_rnd_next 而这个会增加103840,
而select * from mrhao_order_info where address like '%AA%' Handler_read_rnd_next 这个会增加103840,而Handler_read_rnd不会增加)
Handler_rollback 0
Handler_savepoint 0
Handler_savepoint_rollback 0
Handler_update 0
Handler_write 132
(以上handler同Handler_delete,只有影响了表里的任何行,才会增加该值)
Innodb_buffer_pool_pages_data 491
Innodb_buffer_pool_pages_dirty 0
Innodb_buffer_pool_pages_flushed 6050
Innodb_buffer_pool_pages_free 0
Innodb_buffer_pool_pages_latched 0
Innodb_buffer_pool_pages_misc 21
Innodb_buffer_pool_pages_total 512
data 包含数据的页数(脏或者干净的)dirty 当前的脏页数。flushed 刷新的页数 free 空页数
latched 锁定的页数(由于这个数据很号资源,所以UNIV_DEBUG 系统上编译使用) misc分配给行锁或者
hash索引管理用的页数 total 是总的页数 total=data+free+misc(5.4上 1页=16k)
Innodb_buffer_pool_read_ahead_rnd 3288
Innodb_buffer_pool_read_ahead_seq 31840
Innodb_buffer_pool_read_requests 3413220598
Innodb_buffer_pool_reads 104184
Innodb_buffer_pool_wait_free 0
Innodb_buffer_pool_write_requests 85786
read_ahead_rnd 表示在初始化innodb时,使用随机预读的个数,这个发生在对一个表有大量随机扫描的查询,read_ahead_seq 在初始化innodb时,使用顺序预读的个数,一般发生在全表顺序扫描,(innodb有两种预读模式:随机预读方式跟顺序预读 http://hi.baidu.com/fishhust/blog/item/7558f41083fdb808213f2efb.html/cmtid/71718e369bb4353a0b55a960 http://dev.mysql.com/doc/refman/5.0/en/innodb-disk-io.html) read_requests 逻辑读请求的个数,reads 不在buffer pool 不得不从磁盘读取的逻辑请求个数,wait_free,一般情况下,在后台像innodb buffer pool写,然后,当需要读或者创建时,而又没有干净的页使用时,就需要等待页面刷新,这个状态就是等待实例进行计数, write_requests 为往buffer pool写入的个数
Innodb_data_fsyncs 32146
Innodb_data_pending_fsyncs 0
Innodb_data_pending_reads 0
Innodb_data_pending_writes 0
Innodb_data_read 1418334208
Innodb_data_reads 146431
Innodb_data_writes 34452
Innodb_data_written 212622848
read 从服务器开启以来,innodb读取的字节数。reads 服务器读取的页数 ,written innodb写入的字节数 writes 服务器写入的页数(1页16K)fsyncs fsyncs()操作数,pending_fsyncs 挂起的fsyncs()操作数 pending_reads 挂起的读 pending_writes挂起的写
Innodb_dblwr_pages_written 6050
Innodb_dblwr_writes 3324
pages_written 双写操作已经写好的页数。 writes 已经执行的双写操作数量
Innodb_log_waits 0
Innodb_log_write_requests 2617
Innodb_log_writes 22335
Innodb_os_log_fsyncs 25566
Innodb_os_log_pending_fsyncs 0
Innodb_os_log_pending_writes 0
Innodb_os_log_written 12722176
Innodb_page_size 16384
Innodb_pages_created 13
Innodb_pages_read 610723
Innodb_pages_written 6050
size编译时,页的大小,一般为16K created 新建的页数 read 读的页数 written 写的页数
Innodb_row_lock_current_waits 0
Innodb_row_lock_time 0
Innodb_row_lock_time_avg 0
Innodb_row_lock_time_max 0
Innodb_row_lock_waits 0
Innodb_rows_deleted 91
Innodb_rows_inserted 824
Innodb_rows_read 1155270834
Innodb_rows_updated 337
deleted 删除的行数 inserted 插入的行数 read扫描时的行数(测试发现不是读取的行数) updated跟新的行数 以上数据只对innodb引擎,而com_ handler_是对所有引擎
Key_blocks_not_flushed 0
Key_blocks_unused 7150
Key_blocks_used 211
Key_read_requests 872516
Key_reads 4553
Key_write_requests 7498
Key_writes 3768
Key_blocks_not_flushed 在 key cache中修改了,但是还没有刷新到磁盘上的块数,Key_blocks_unused 未使用的块数(key_buffer控制),
Key_blocks_used 使用的块数Key_read_requests 从cache中读取的请求数,Key_reads 从磁盘读取的块数,用Key_reads/Key_read_requests来计算cache的miss rate
Key_write_requests 写入cache的请求数,Key_writes 写入磁盘的块数
(注: 内存与磁盘交互的是块数,而cache的请求数为操作的行数。myisam 中data 与index是文件是分离的,当insert 数据的时候,myisam会直接插入数据到磁盘,但不会立即插入index到磁盘上,而是直接插入key_buffer中,而不刷新到磁盘上,所以有时候 Key_blocks_not_flushed 与Key_write_requests 可能会很高,但Key_writes 确很低,可用“flush table 表名” 强制刷新index到磁盘上。如果大量的块没有flush到磁盘上,若服务器这时候出现故障,myisam会在下次重启时,根据data文件重建 index文件,若没有重建成功,可用”repair table 表名“修理表 )
Last_query_cost 0.000000
查询优化器计算的最后编译的查询的总成本,这个在对于同一语句,来对比不同优化器很有用,默认为0,该变量为session变量
Max_used_connections 22
服务器启动后,同时使用的连接的最大数量。
Not_flushed_delayed_rows 0
等待写入INSERT DELAY队列的行数
Open_files
Open_streams
Open_table_definitions
Open_tables
Opened_files
Opened_table_definitions
Opened_tables
Open_files 打开文件的个数,这个统计是服务器打开的正规文件的个数。不包括socket 及pipe。当打开myisam表数据时,他会增加两个(数据文件与索引文件),当打开innodb表时,该值不增加,当打开的myisam表已另一个别 名打开时,Open_files只会增加一个。flush tables 会清空该值
Opened_files,当增加Open_files同时,他会已同样大小增加该值。当table_open_cache增加,或者flush tables 时,该值是不会减少,但也不增加的。
Open_table_definitions 打开表时被cache的frm文件个数。
Open_tables 打开表的个数。
Opened_table_definitions 与 Opened_tables 的解释与Opened_files差不多(跟网上说的只有当
table cache 到达table_open_cache时,才会增加Opened_files这值不一样哦),以上状态有global 跟session
Prepared_stmt_count 0
当前prepared statements的个数,最大数会由变量max_prepared_stmt_count控制 ,当DEALLOCATE PREPARE时,改状态值会减小
Qcache_free_blocks 0
Qcache_free_memory 0
Qcache_hits 0
Qcache_inserts 0
Qcache_lowmem_prunes 0
Qcache_not_cached 0
Qcache_queries_in_cache 0
Qcache_total_blocks 0
Qcache_total_blocks 显示了所有的块数(未使用的内存跟已使用),而Qcache_free_blocks 反映了未使用的块数。如果Qcache_free_blocks很大(如果没有内存碎片的话,应该为1),说明内存的碎片很多,内存的使用率会比较差,所 以这时虽然 Qcache_free_memory显示还有剩余的内存,也可能无法使用,当插入新的query时就需要清除旧的,使得 Qcache_lowmem_prunes很高。可以使用
flush query cache重整内存,操作之后Qcache_free_blocks应该为1,因为所有未使用的内存都放在一起作为连续的一块了
Queries
被服务器执行的语句个数,包括存储过程里的语句,也包括show status之类的
Questions 19483094
被服务器执行的语句个数, 但是不包括存储过程里面的语句
Rpl_status NULL (暂时未使用)
Select_full_join 0
Select_full_range_join 0
Select_range 0
Select_range_check 0
Select_scan 1
有兴趣可以看看下面内容
http://hackmysql.com/selectandsort
在优化器explain中,显示的第一个表或者唯一的一个表他会影响: Select_scan and Select_range,
第二个表或子表会影响: Select_full_join, Select_range_check, and Select_full_range_join
show session status like "select%";的值会按照以下规则来增加
1;Select_scan 当顺序的从磁盘读取时,会增加该值,如explain中第一个表的type" 列显示ALL
EXPLAIN select * from t1,t2
2:Select_range 当explain中第一个表的type" 列显示range时,该值增加
EXPLAIN select * from t1,t2 where t1.c1>7800 and t1.c1<8000 and t1.c1=t2.c1
3:Select_full_join explain当第二个表或子表的“type" 列显示ALL
EXPLAIN select * from t1,t2 where t1.c1>7800 and t1.c1<8000 and t1.c2=t2.c2
4:Select_full_range_join explain的第二个表或子表为range时 该值增加
EXPLAIN select * from t1,t2 where t1.c1>7800 and t1.c1<8000 and t2.c1<1000 这个会增加Select_full_range_join 及Select_range
5:Select_range_check 的意思是不确定range的范围,
如:EXPLAIN select * from t2,t1 where t2.c1<t1.c2;第二个表显示:Range checked for each record (index map: 0x1)
Sort_merge_passes 0
Sort_range 0
Sort_rows 0
Sort_scan 0
一般的,查询sort都会经历三个步骤
1. 查找where条件的值
2. 排序值
3. 读排序后的行
当在第一步时增加Select_scan, 则第三步就会是 增加Sort_scan. 如果第一步是增加 Select_range,则第三步就是 增加Sort_range.
Sort_merge_passes 包括两步。MySQL 首先会尝试在内存中做排序,使用的内存大小由系统变量 Sort_buffer_size 决定,如果它的大小不够把所有的记录都读到内存中,MySQL 就会把每次在内存中排序的结果存到临时文件中,这时候会增加Sort_merge_passes。等 MySQL 找到所有记录之后,再把临时文件中的记录做一次排序。实际上,MySQL 会用另一个临时文件来存再次排序的结果,所以通常会看到 Sort_merge_passes 增加的数值是建临时文件数的两倍。因为用到了临时文件,所以速度可能会比较慢,增加 Sort_buffer_size 会减少 Sort_merge_passes 和 创建临时文件的次数。但盲目的增加 Sort_buffer_size 并不一定能提高速度,
Slave_open_temp_tables 0
Slave_retried_transactions 0
Slave_running OFF
Slow_launch_threads 0
The number of threads that have taken more than slow_launch_time seconds to create.
Slow_queries 0
The number of queries that have taken more than long_query_time seconds.
Table_locks_immediate 24364829
Table_locks_waited 0
Table_locks_immediate 立即获得的表的锁的次数。
Table_locks_waited 不能立即获得的表的锁的次数。
Threads_cached 0
Threads_connected 12
Threads_created 4191
Threads_running 1
Threads_cached 线程的缓存值,
Threads_connected 当前打开的连接的数量。
Threads_created 创建用来处理连接的线程数。如果Threads_created较大,你可能要增加thread_cache_size值。缓存访问率的计算方法 Threads_created(新建的线程)/Connections(只要有线程连接,该值就增加)。
Threads_running 激活的(非睡眠状态)线程数。
Uptime 978671
The number of seconds that the server has been up.
Uptime_since_flush_status 978671
The number of seconds since the most recent FLUSH STATUS statement(FLUSH STATUS,是把当前的session值加到global上,并重置key-cache及把Max_used_connections值变为当前的连接 数).
mysql/db | 评论:0
| Trackbacks:0
| 阅读:993
Submitted by admin on 2012, April 12, 6:06 PM
Mysql Explain 详解
一.语法
explain < table_name >
例如: explain select * from t3 where id=3952602;
二.explain输出解释
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
1.id
我的理解是SQL执行的顺利的标识,SQL从大到小的执行.
例如:
mysql> explain select * from (select * from ( select * from t3 where id=3952602) a) b;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DERIVED | <derived3> | system | NULL | NULL | NULL | NULL | 1 | |
| 3 | DERIVED | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
很显然这条SQL是从里向外的执行,就是从id=3 向上执行.
2. select_type
就是select类型,可以有以下几种
(1) SIMPLE
简单SELECT(不使用UNION或子查询等) 例如:
mysql> explain select * from t3 where id=3952602;
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | const | 1 | |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
(2). PRIMARY
我的理解是最外层的select.例如:
mysql> explain select * from (select * from t3 where id=3952602) a ;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DERIVED | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
(3).UNION
UNION中的第二个或后面的SELECT语句.例如
mysql> explain select * from t3 where id=3952602 union all select * from t3 ;
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
| 1 | PRIMARY | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | const | 1 | |
| 2 | UNION | t3 | ALL | NULL | NULL | NULL | NULL | 1000 | |
|NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
(4).DEPENDENT UNION
UNION中的第二个或后面的SELECT语句,取决于外面的查询
mysql> explain select * from t3 where id in (select id from t3 where id=3952602 union all select id from t3) ;
+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+
| 1 | PRIMARY | t3 | ALL | NULL | NULL | NULL | NULL | 1000 | Using where |
| 2 | DEPENDENT SUBQUERY | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | const | 1 | Using index |
| 3 | DEPENDENT UNION | t3 | eq_ref | PRIMARY,idx_t3_id | PRIMARY | 4 | func | 1 | Using where; Using index |
|NULL | UNION RESULT | <union2,3> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------------+------------+--------+-------------------+---------+---------+-------+------+--------------------------+
(4).UNION RESULT
UNION的结果。
mysql> explain select * from t3 where id=3952602 union all select * from t3 ;
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
| 1 | PRIMARY | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | const | 1 | |
| 2 | UNION | t3 | ALL | NULL | NULL | NULL | NULL | 1000 | |
|NULL | UNION RESULT | <union1,2> | ALL | NULL | NULL | NULL | NULL | NULL | |
+----+--------------+------------+-------+-------------------+---------+---------+-------+------+-------+
(5).SUBQUERY
子查询中的第一个SELECT.
mysql> explain select * from t3 where id = (select id from t3 where id=3952602 ) ;
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------------+
| 1 | PRIMARY | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | const | 1 | |
| 2 | SUBQUERY | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | | 1 | Using index |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------------+
(6). DEPENDENT SUBQUERY
子查询中的第一个SELECT,取决于外面的查询
mysql> explain select id from t3 where id in (select id from t3 where id=3952602 ) ;
+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+
| 1 | PRIMARY | t3 | index | NULL | PRIMARY | 4 | NULL | 1000 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | const | 1 | Using index |
+----+--------------------+-------+-------+-------------------+---------+---------+-------+------+--------------------------+
(7).DERIVED
派生表的SELECT(FROM子句的子查询)
mysql> explain select * from (select * from t3 where id=3952602) a ;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DERIVED | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
3.table
显示这一行的数据是关于哪张表的.
有时不是真实的表名字,看到的是derivedx(x是个数字,我的理解是第几步执行的结果)
mysql> explain select * from (select * from ( select * from t3 where id=3952602) a) b;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DERIVED | <derived3> | system | NULL | NULL | NULL | NULL | 1 | |
| 3 | DERIVED | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
4.type
这列很重要,显示了连接使用了哪种类别,有无使用索引.
从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALL
(1).system
这是const联接类型的一个特例。表仅有一行满足条件.如下(t3表上的id是 primary key)
mysql> explain select * from (select * from t3 where id=3952602) a ;
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
| 1 | PRIMARY | <derived2> | system | NULL | NULL | NULL | NULL | 1 | |
| 2 | DERIVED | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | | 1 | |
+----+-------------+------------+--------+-------------------+---------+---------+------+------+-------+
(2).const
表最多有一个匹配行,它将在查询开始时被读取。因为仅有一行,在这行的列值可被优化器剩余部分认为是常数。const表很快,因为它们只读取一次!
const用于用常数值比较PRIMARY KEY或UNIQUE索引的所有部分时。在下面的查询中,tbl_name可以用于const表:
SELECT * from tbl_name WHERE primary_key=1;
SELECT * from tbl_name WHERE primary_key_part1=1和 primary_key_part2=2;
例如:
mysql> explain select * from t3 where id=3952602;
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | t3 | const | PRIMARY,idx_t3_id | PRIMARY | 4 | const | 1 | |
+----+-------------+-------+-------+-------------------+---------+---------+-------+------+-------+
(3). eq_ref
对于每个来自于前面的表的行组合,从该表中读取一行。这可能是最好的联接类型,除了const类型。它用在一个索引的所有部分被联接使用并且索引是UNIQUE或PRIMARY KEY。
eq_ref可以用于使用= 操作符比较的带索引的列。比较值可以为常量或一个使用在该表前面所读取的表的列的表达式。
在下面的例子中,MySQL可以使用eq_ref联接来处理ref_tables:
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
例如
mysql> create unique index idx_t3_id on t3(id) ;
Query OK, 1000 rows affected (0.03 sec)
Records: 1000 Duplicates: 0 Warnings: 0
mysql> explain select * from t3,t4 where t3.id=t4.accountid;
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+
| 1 | SIMPLE | t4 | ALL | NULL | NULL | NULL | NULL | 1000 | |
| 1 | SIMPLE | t3 | eq_ref | PRIMARY,idx_t3_id | idx_t3_id | 4 | dbatest.t4.accountid | 1 | |
+----+-------------+-------+--------+-------------------+-----------+---------+----------------------+------+-------+
(4).ref
对于每个来自于前面的表的行组合,所有有匹配索引值的行将从这张表中读取。如果联接只使用键的最左边的前缀,或如果键不是UNIQUE或PRIMARY KEY(换句话说,如果联接不能基于关键字选择单个行的话),则使用ref。如果使用的键仅仅匹配少量行,该联接类型是不错的。
ref可以用于使用=或<=>操作符的带索引的列。
在下面的例子中,MySQL可以使用ref联接来处理ref_tables:
SELECT * FROM ref_table WHERE key_column=expr;
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column=other_table.column;
SELECT * FROM ref_table,other_table
WHERE ref_table.key_column_part1=other_table.column
AND ref_table.key_column_part2=1;
例如:
mysql> drop index idx_t3_id on t3;
Query OK, 1000 rows affected (0.03 sec)
Records: 1000 Duplicates: 0 Warnings: 0
mysql> create index idx_t3_id on t3(id) ;
Query OK, 1000 rows affected (0.04 sec)
Records: 1000 Duplicates: 0 Warnings: 0
mysql> explain select * from t3,t4 where t3.id=t4.accountid;
+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+
| 1 | SIMPLE | t4 | ALL | NULL | NULL | NULL | NULL | 1000 | |
| 1 | SIMPLE | t3 | ref | PRIMARY,idx_t3_id | idx_t3_id | 4 | dbatest.t4.accountid | 1 | |
+----+-------------+-------+------+-------------------+-----------+---------+----------------------+------+-------+
2 rows in set (0.00 sec)
(5). ref_or_null
该联接类型如同ref,但是添加了MySQL可以专门搜索包含NULL值的行。在解决子查询中经常使用该联接类型的优化。
在下面的例子中,MySQL可以使用ref_or_null联接来处理ref_tables:
SELECT * FROM ref_table
WHERE key_column=expr OR key_column IS NULL;
(6). index_merge
该联接类型表示使用了索引合并优化方法。在这种情况下,key列包含了使用的索引的清单,key_len包含了使用的索引的最长的关键元素。
例如:
mysql> explain select * from t4 where id=3952602 or accountid=31754306 ;
+----+-------------+-------+-------------+----------------------------+----------------------------+---------+------+------+------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------------+----------------------------+----------------------------+---------+------+------+------------------------------------------------------+
| 1 | SIMPLE | t4 | index_merge | idx_t4_id,idx_t4_accountid | idx_t4_id,idx_t4_accountid | 4,4 | NULL | 2 | Using union(idx_t4_id,idx_t4_accountid); Using where |
+----+-------------+-------+-------------+----------------------------+----------------------------+---------+------+------+------------------------------------------------------+
1 row in set (0.00 sec)
(7). unique_subquery
该类型替换了下面形式的IN子查询的ref:
value IN (SELECT primary_key FROM single_table WHERE some_expr)
unique_subquery是一个索引查找函数,可以完全替换子查询,效率更高。
(8).index_subquery
该联接类型类似于unique_subquery。可以替换IN子查询,但只适合下列形式的子查询中的非唯一索引:
value IN (SELECT key_column FROM single_table WHERE some_expr)
(9).range
只检索给定范围的行,使用一个索引来选择行。key列显示使用了哪个索引。key_len包含所使用索引的最长关键元素。在该类型中ref列为NULL。
当使用=、<>、>、>=、<、<=、IS NULL、<=>、BETWEEN或者IN操作符,用常量比较关键字列时,可以使用range
mysql> explain select * from t3 where id=3952602 or id=3952603 ;
+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+
| 1 | SIMPLE | t3 | range | PRIMARY,idx_t3_id | idx_t3_id | 4 | NULL | 2 | Using where |
+----+-------------+-------+-------+-------------------+-----------+---------+------+------+-------------+
1 row in set (0.02 sec)
(10).index
该联接类型与ALL相同,除了只有索引树被扫描。这通常比ALL快,因为索引文件通常比数据文件小。
当查询只使用作为单索引一部分的列时,MySQL可以使用该联接类型。
(11). ALL
对于每个来自于先前的表的行组合,进行完整的表扫描。如果表是第一个没标记const的表,这通常不好,并且通常在它情况下很差。通常可以增加更多的索引而不要使用ALL,使得行能基于前面的表中的常数值或列值被检索出。
5.possible_keys
possible_keys列指出MySQL能使用哪个索引在该表中找到行。注意,该列完全独立于EXPLAIN输出所示的表的次序。这意味着在possible_keys中的某些键实际上不能按生成的表次序使用。
如果该列是NULL,则没有相关的索引。在这种情况下,可以通过检查WHERE子句看是否它引用某些列或适合索引的列来提高你的查询性能。如果是这样,创造一个适当的索引并且再次用EXPLAIN检查查询
6. key
key列显示MySQL实际决定使用的键(索引)。如果没有选择索引,键是NULL。要想强制MySQL使用或忽视possible_keys列中的索引,在查询中使用FORCE INDEX、USE INDEX或者IGNORE INDEX。
7.key_len
key_len列显示MySQL决定使用的键长度。如果键是NULL,则长度为NULL。
使用的索引的长度。在不损失精确性的情况下,长度越短越好
8. ref
ref列显示使用哪个列或常数与key一起从表中选择行。
9. rows
rows列显示MySQL认为它执行查询时必须检查的行数。
10. Extra
该列包含MySQL解决查询的详细信息,下面详细.
(1).Distinct
一旦MYSQL找到了与行相联合匹配的行,就不再搜索了
(2).Not exists
MYSQL优化了LEFT JOIN,一旦它找到了匹配LEFT JOIN标准的行,
就不再搜索了
(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,这就会发生,或者是查询有问题
mysql/db | 评论:0
| Trackbacks:0
| 阅读:950
Submitted by admin on 2012, April 12, 6:06 PM
先说下tmp_table_size吧:
它规定了内部内存临时表的最大值,每个线程都要分配。(实际起限制作用的是tmp_table_size和max_heap_table_size的最小值。)如果内存临时表超出了限制,MySQL就会自动地把它转化为基于磁盘的MyISAM表,存储在指定的tmpdir目录下,默认:
mysql> show variables like "tmpdir";
+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| tmpdir | /tmp/ |
+---------------+-------+
优化查询语句的时候,要避免使用临时表,如果实在避免不了的话,要保证这些临时表是存在内存中的。如果需要的话并且你有很多group by语句,并且你有很多内存,增大tmp_table_size(和max_heap_table_size)的值。这个变量不适用与用户创建的内存表(memory table).
你可以比较内部基于磁盘的临时表的总数和创建在内存中的临时表的总数(Created_tmp_disk_tables和Created_tmp_tables),一般的比例关系是:
Created_tmp_disk_tables/Created_tmp_tables<5%
max_heap_table_size
这个变量定义了用户可以创建的内存表(memory table)的大小.这个值用来计算内存表的最大行数值。这个变量支持动态改变,即set @max_heap_table_size=#
,但是对于已经存在的内存表就没有什么用了,除非这个表被重新创建(create table)或者修改(alter table)或者truncate table。服务重启也会设置已经存在的内存表为全局max_heap_table_size的值。
这个变量和tmp_table_size一起限制了内部内存表的大小。
mysql/db | 评论:0
| Trackbacks:0
| 阅读:990
Submitted by admin on 2012, March 31, 6:48 PM
.Centos5.5 ext4支持的安装与升级:
yum -y install e4fsprogs
这就可以了,下面的仅供参考
在 RHEL 和 Centos5 中使用 Ext4 前,很多想可能想先给现有的文件系统转换成 Ext4 ,只要运行下面的命令就行了
tune4fs -O extents,uninit_bg,dir_index,flex_bg /dev/sdb1
在重起前,我还要让内核支持 Ext4 的文件系统,需要修改 initrd 的文件本身的内容。如下命令来生成 支持 Ext4 的 initrd。
mkinitrd --with=ext4 --with=ext3 -f /boot/initrd-2.6.18-194.32.1.el5.img 2.6.18-194.32.1
ext4对我来说的优点是,每个子目录支持无限多个文件
ext3只能支持 32000个
NTFS也是无限多,但Linux用NTFS性能有折扣
下面是Ext4,Ext3的特点和区别:
Linux kernel 自 2.6.28 开始正式支持新的文件系统 Ext4。 Ext4 是 Ext3 的改进版,修改了 Ext3 中部分重要的数据结构,而不仅仅像 Ext3 对 Ext2 那样,只是增加了一个日志功能而已。Ext4 可以提供更佳的性能和可靠性,还有更为丰富的功能:
1. 与 Ext3 兼容。 执行若干条命令,就能从 Ext3 在线迁移到 Ext4,而无须重新格式化磁盘或重新安装系统。原有 Ext3 数据结构照样保留,Ext4 作用于新数据,当然,整个文件系统因此也就获得了 Ext4 所支持的更大容量。
2. 更大的文件系统和更大的文件。 较之 Ext3 目前所支持的最大 16TB 文件系统和最大 2TB 文件,Ext4 分别支持 1EB(1,048,576TB, 1EB=1024PB, 1PB=1024TB)的文件系统,以及 16TB 的文件。
3. 无限数量的子目录。 Ext3 目前只支持 32,000 个子目录,而 Ext4 支持无限数量的子目录。
4. Extents。 Ext3 采用间接块映射,当操作大文件时,效率极其低下。比如一个 100MB 大小的文件,在 Ext3 中要建立 25,600 个数据块(每个数据块大小为 4KB)的映射表。而 Ext4 引入了现代文件系统中流行的 extents 概念,每个 extent 为一组连续的数据块,上述文件则表示为“该文件数据保存在接下来的 25,600 个数据块中”,提高了不少效率。
5. 多块分配。 当 写入数据到 Ext3 文件系统中时,Ext3 的数据块分配器每次只能分配一个 4KB 的块,写一个 100MB 文件就要调用 25,600 次数据块分配器,而 Ext4 的多块分配器“multiblock allocator”(mballoc) 支持一次调用分配多个数据块。
6. 延迟分配。 Ext3 的数据块分配策略是尽快分配,而 Ext4 和其它现代文件操作系统的策略是尽可能地延迟分配,直到文件在 cache 中写完才开始分配数据块并写入磁盘,这样就能优化整个文件的数据块分配,与前两种特性搭配起来可以显著提升性能。
7. 快速 fsck。 以前执行 fsck 第一步就会很慢,因为它要检查所有的 inode,现在 Ext4 给每个组的 inode 表中都添加了一份未使用 inode 的列表,今后 fsck Ext4 文件系统就可以跳过它们而只去检查那些在用的 inode 了。
8. 日志校验。 日志是最常用的部分,也极易导致磁盘硬件故障,而从损坏的日志中恢复数据会导致更多的数据损坏。Ext4 的日志校验功能可以很方便地判断日志数据是否损坏,而且它将 Ext3 的两阶段日志机制合并成一个阶段,在增加安全性的同时提高了性能。
9. “无日志”(No Journaling)模式。 日志总归有一些开销,Ext4 允许关闭日志,以便某些有特殊需求的用户可以借此提升性能。
10. 在线碎片整理。 尽管延迟分配、多块分配和 extents 能有效减少文件系统碎片,但碎片还是不可避免会产生。Ext4 支持在线碎片整理,并将提供 e4defrag 工具进行个别文件或整个文件系统的碎片整理。
11. inode 相关特性。 Ext4 支持更大的 inode,较之 Ext3 默认的 inode 大小 128 字节,Ext4 为了在 inode 中容纳更多的扩展属性(如纳秒时间戳或 inode 版本),默认 inode 大小为 256 字节。Ext4 还支持快速扩展属性(fast extended attributes)和 inode 保留(inodes reservation)。
12. 持久预分配(Persistent preallocation)。 P2P 软件为了保证下载文件有足够的空间存放,常常会预先创建一个与所下载文件大小相同的空文件,以免未来的数小时或数天之内磁盘空间不足导致下载失败。 Ext4 在文件系统层面实现了持久预分配并提供相应的 API(libc 中的 posix_fallocate()),比应用软件自己实现更有效率。
13. 默认启用 barrier。 磁 盘上配有内部缓存,以便重新调整批量数据的写操作顺序,优化写入性能,因此文件系统必须在日志数据写入磁盘之后才能写 commit 记录,若 commit 记录写入在先,而日志有可能损坏,那么就会影响数据完整性。Ext4 默认启用 barrier,只有当 barrier 之前的数据全部写入磁盘,才能写 barrier 之后的数据。(可通过 "mount -o barrier=0" 命令禁用该特性。)
linux | 评论:0
| Trackbacks:0
| 阅读:1112
Submitted by admin on 2012, March 31, 6:45 PM
使用环境使用的是CentOS5.5 内核是2.6.18-194.el5
其实CentOS 5.5里面是有ext4模块的,只是没加载,所以我们先把模块加入系统
[root@linux ~]# cd /lib/modules/2.6.18-194.el5/kernel/fs/ext4/ //ext4模块就在此目录下
[root@linux ext4]# ls
ext4.ko
找到模块后使用modprobe命令添加
[root@linux ext4]# modprobe ext4 //注意:这里只能写模块名,不能写成ext4.ko
添加完后使用lsmod查看
[root@linux ext4]# lsmod |grep ext4
ext4 285409 0
jbd2 47744 1 ext4
crc16 1027 1 ext4
最后使用yum安装一下e4fsprogs
[root@linux ext4]# yum install e4fsprogs
最后创建一个分区来使用ext4创建文件系统
[root@linux ~]# mkfs.ext4 /dev/sda6
到此你的linux系统已经能够支持ext4文件系统了!
linux | 评论:0
| Trackbacks:0
| 阅读:1153
Submitted by admin on 2012, March 31, 5:49 PM
现在固态硬盘越来越流行,如何使用固态硬盘?本人参考了一些国外最新的资料,总结如下:
参考:
http://en.opensuse.org/SDB:SSD_discard_%28trim%29_support
1、内核支持。kernel版本>2.6.37 中包含只针对ext4文件的FITRIM的系统调用。
因此要使用固态硬盘,内核版本必需大于2.6.33,由于2.6.37针对ext4下的固态硬盘进行了优化建议采用2.6.37以上版本,同时文件系统采用ext4。
2、如何使用ssd的TRIM功能。
下载最新版的hdparm,最新版的hdparm支持linux下的trim,也就是discard。
在/etc/rc.local下增加/sbin/wiper.sh
在/etc/fstab 下修改为如下:
/dev/sda1 / ext4 discard,defaults
增加discard选项即可。
几点建议:
1、将/tmp 和 /var/tmp目录挂载到内存中,避免对ssd频繁读写
tmpfs /tmp tmpfs defaults,noatime,mode=1777 0 0
tmpfs /var/tmp tmpfs defaults,noatime,mode=1777 0 0
why not btrfs?
tmpfs on /var/run type tmpfs (rw,nosuid,nodev,noexec,relatime,mode=755)
tmpfs on /media type tmpfs (rw,nosuid,nodev,noexec,relatime,mode=755)
tmpfs on /var/lock type tmpfs (rw,nosuid,nodev,noexec,relatime,mode=755)
tmpfs on /tmp type tmpfs (rw,relatime)
/dev/sda2 on / type btrfs (rw,noatime,nodiratime,ssd)
原本在机械硬盘上,写入数据时,系统会通知硬盘先将以前的擦除,再将新的数据写入到磁盘中。而在删除数据时,系统只会在此处做个标记,说明这里应该是没有东西了,等到真正要写入数据时再来真正删除,并且做标记这个动作会保留在磁盘缓存中,等到磁盘空闲时再执行。而当系统识别到SSD并确认SSD支持Trim后,在删除数据时,会不向硬盘通知删除指令,只使用Volume Bitmap来记住这里的数据已经删除。Volume Bitmap只是一个磁盘快照,其建立速度比直接读写硬盘去标记删除区域要快得多。这一步就已经省下一大笔时间了。然后再是写入数据的时候,由于NAND闪存保存数据是纯粹的数字形式,因此可以直接根据Volume Bitmap的情况,向快照中已删除的区块写入新的数据,而不用花时间去擦除原本的数据。
以上就是Trim的原理以及真正作用。
--------------------------------
Linux下的trim支持叫discard,现在ext4和xfs都支持(btrfs应该也支持),内核需要>=2.6.37,xfs的支持在3.0才比较完善。具体需要设置这几个方面:
1. 内核
升级到2.6.37以上,最好用最新的3.0。
禁用disk IO scheduler模块。
2. 文件系统表
修改fstab文件,在挂载参数中加上discard;最好也同时加上noatime。
3. 调整文件系统参数
ext4的话最好禁用日志功能,能防止写入额外的数据而减少ssd寿命。
4. 相关文档:
xfs官网对ssd支持的说明
ext4的ssd设置
suse官方对ssd支持的相关说明
fdisk -H 224 -S 56 /dev/sdd
fdisk -H 32 -S 32 /dev/sdd
配置固态硬盘(SSD)的Ext 4
接着需要关注的就是文件系统。想要优化文件系统删除字节区块的效率,就必须确保小于512K的文件分布在不同的删除字节区块上。要做到这一点,必须确保在创建可扩展文件系统时指定了需要使用的条带的宽度和幅度。这些值在页面中指定,默认大小为4KB。要创建一个最佳的可扩展文件系统,应该使用如下命令:
mkfs.ext4 -E stride=128,stripe-width=128 /dev/sda1
如果要修改现有的文件系统的参数,可以使用tune2fs实用程序:
tune2fs -E stride=128,stripe-width=128 /dev/sda1
配置固态硬盘(SSD)的I/O调度程序
优化的第三个部分涉及到I/O调度程序。该模块是一个决定如何处理I/O请求的核心组件。默认情况下就是非常公平的排队,对于普通的磁盘驱动器来说,这是很好的方案,但对于以期限调度为优势的固态硬盘来说,这并不是最好的。
如果你想在系统中对所有磁盘采用期限调度,可以在内核加载时把elevator=deadline这句话加入到系统引导管理器(GURB)中;如果你只是想针对某一个磁盘,就应该在rc.local文件中加入类似如下实例的一句话,那么每次当系统重启,期限调度就会应用到指定的磁盘。如下实例将会对/dev/sdb磁盘采用期限调度。
echo deadline > /sys/block/sda/queue/scheduler
清理固态硬盘(SSD)中的数据块
最后一个重要的步骤称为“清理”,该操作可以确保在删除文件后相应的数据块真正清空,然后在创建新的文件时才能有可用的数据块。如果没有清理操作,一旦数据块空间填满,固态硬盘的性能就会下降。如果使用丢弃挂载选项,当文件删除后,数据块也会被相应地清除,这样可以显著提高固态硬盘的性能。2.6.33以上的内核已经支持清理操作。
要启用清理功能,需要在固态硬盘的/etc/fstab配置中为挂载文件系统添加丢弃选项。示例中的命令为挂载的根逻辑卷启用了清理操作。
/dev/system/root/ext4 discard,errors=remount-ro,noatime 0 1
该命令同时也添加了Noatime选项,该选项保证了文件的访问时间不会因为每次读取而更新,从而降低对文件系统的写入次数。
在fasab配置文件中完成对文件系统的这些修改后,重启计算机,或者通知文件系统重新读取其配置,然后使用/etc/fstab文件中包含的mount -o命令重新安装每个文件系统。
linux | 评论:0
| Trackbacks:0
| 阅读:2524
Submitted by admin on 2012, March 31, 3:59 PM
CentOS 5.8是 CentOS 5 发行系列的第六次更新。它包含了很多错误修正、升级和新功能。在往下读之前我们推荐您先阅读 UOP 的发行注记(或单页发行注记)及技术性注记(或单页技术性注记)。本文档的额外部分只作为一个附录并主要涉及关于 CentOS 的问题。
如果你之前已经安装了CentOS 5.5,打算在近期升级到CentOS 5.8,那么以下内容是你需要关注的:
首先,做好备份(你应该知道应该备份什么),这个不用多说。
然后,执行以下命令:
yum clean all
yum update glibc*
yum update yum* rpm* python*
yum clean all
yum update
reboot
yum clean allyum update glibc* yum update yum* rpm* python*yum clean allyum updatereboot
这样就升级完了,可以检查一下系统目前的版本:
lsb_release -a注意:如果你的CentOS上安装了ISPConfig,那么有可能会启动了CentOS Testing软件源:-kbs-CentOS-Testing,这可能会造成依赖性问题。
用以下命令升级可以禁止kbs-CentOS-Testing:
yum update --exclude="postfix" --disablerepo=kbs-CentOS-Testing
linux | 评论:0
| Trackbacks:0
| 阅读:1074
Submitted by admin on 2012, March 31, 3:59 PM
CentOS 内核的内核是操作系统最基本的部分。它是为众多应用程序提供对计算机硬件的安全访问的一部分软件,这种访问是有限的,并且CentOS 内核决定一个程序在什么时候对某部分硬件操作多长时间。直接对硬件操作是非常复杂的,所以内核通常提供一种硬件抽象的方法来完成这些操作。
ReiserFS是一种新型的文件系统,它通过一种与众不同的方式--完全平衡树结构来容纳数据,包括文件数据,文件名以及日志支持。ReiserFS还以支持海量磁盘和磁盘阵列,并能在上面继续保很快的搜索速度和很高的效率。
本实例在x86_64环境下升级
1. 查看CentOS 内核升级包
yum --disablerepo updates,base --enablerepo=centosplus list 'kernel*'
2. 安装要升级的kernel包名称
yum --disablerepo updates,base --enablerepo=centosplus install kernel.x86_64
3. 安装reiserfs工具
yum --disablerepo updates,base --enablerepo=centosplus install reiserfs-utils.x86_64
4. 通过fdisk创建分区
fdisk /dev/sda
partprobe
5. 使用mkfs.reiserfs工具格式化分区(N为刚创建分区的分区数)
mkfs.reiserfs /dev/sdaN
这样,我们就完成了用yum升级 CentOS 内核,并且让升级后的 CentOS 内核支持reiserfs。
linux | 评论:0
| Trackbacks:0
| 阅读:976