<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>索引 &#8211; LPC影子技术分享</title>
	<atom:link href="https://www.mudbest.com/tag/%E7%B4%A2%E5%BC%95/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.mudbest.com</link>
	<description>行影不离,忘之却步.</description>
	<lastBuildDate>Mon, 08 Oct 2012 08:08:01 +0000</lastBuildDate>
	<language>zh-Hans</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.1.1</generator>
	<item>
		<title>MyISAM与Innodb的比较</title>
		<link>https://www.mudbest.com/myisam%e4%b8%8einnodb%e7%9a%84%e6%af%94%e8%be%83/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Sat, 15 Sep 2012 06:47:17 +0000</pubDate>
				<category><![CDATA[Mysql]]></category>
		<category><![CDATA[分享]]></category>
		<category><![CDATA[Innodb]]></category>
		<category><![CDATA[MyISAM]]></category>
		<category><![CDATA[索引]]></category>
		<guid isPermaLink="false">http://www.mudbest.com/?p=1170</guid>

					<description><![CDATA[从mysql-5.5.5开始,InnoDB作为默认存储引擎，InnoDB作为支持事务的存储引擎，拥有相关的RD ... <a title="MyISAM与Innodb的比较" class="read-more" href="https://www.mudbest.com/myisam%e4%b8%8einnodb%e7%9a%84%e6%af%94%e8%be%83/" aria-label="阅读 MyISAM与Innodb的比较">阅读更多</a>]]></description>
										<content:encoded><![CDATA[<p>从mysql-5.5.5开始,InnoDB作为默认存储引擎，InnoDB作为支持事务的存储引擎，拥有相关的RDBMS特性：包括ACID事务支持，参考完整性（外健），灾难恢复能力等特性。<br />
同时作为维护mysql内部结构的mysql和information_schema两个databases中的表，依然使用MyISAM存储引擎，而且不能被更改为InnoDB，一般来说不是有太多人关心这个东西。决定使用什么样的存储引擎是一个很tricky的事情，但是还是值我们去研究一下，这里的文章只考虑 MyISAM 和InnoDB这两个，因为这两个是最常见的。   </p>
<p>myisam只有索引缓存  <span id="more-1170"></span></p>
<p>innodb不分索引文件数据文件 innodb buffer  </p>
<p>myisam只能管理索引，在索引数据大于分配的资源时，会由操作系统来cache；数据文件依赖于操作系统的cache。innodb不管是索引还是数据，都是自己来管理  </p>
<p>思考上面这些问题可以让你找到合适的方向，但那并不是绝对的。如果你需要事务处理或是外键，那么InnoDB 可能是比较好的方式。如果你需要全文索引，那么通常来说 MyISAM是好的选择，因为这是系统内建的，然而，我们其实并不会经常地去测试两百万行记录。所以，就算是慢一点，我们可以通过使用Sphinx从InnoDB中获得全文索引。  </p>
<p>数据的大小，是一个影响你选择什么样存储引擎的重要因素，大尺寸的数据集趋向于选择InnoDB方式，因为其支持事务处理和故障恢复。数据库的在小决定了故障恢复的时间长短，InnoDB可以利用事务日志进行数据恢复，这会比较快。而MyISAM可能会需要几个小时甚至几天来干这些事，InnoDB只需要几分钟。  </p>
<p>您操作数据库表的习惯可能也会是一个对性能影响很大的因素。比如： COUNT() 在 MyISAM 表中会非常快，而在InnoDB 表下可能会很痛苦。而主键查询则在InnoDB下会相当相当的快，但需要小心的是如果我们的主键太长了也会导致性能问题。大批的inserts 语句在 MyISAM下会快一些，但是updates 在InnoDB 下会更快一些——尤其在并发量大的时候。  </p>
<p>所以，到底你检使用哪一个呢？根据经验来看，如果是一些小型的应用或项目，那么MyISAM 也许会更适合。当然，在大型的环境下使用 MyISAM 也会有很大成功的时候，但却不总是这样的。如果你正在计划使用一个超大数据量的项目，而且需要事务处理或外键支持，那么你真的应该直接使用 InnoDB方式。但需要记住InnoDB 的表需要更多的内存和存储，转换100GB 的MyISAM 表到InnoDB 表可能会让你有非常坏的体验。  </p>
<p>===========================================================  </p>
<p>MyISAM:这个是默认类型,它是基于传统的ISAM类型,ISAM是 Indexed Sequential Access Method (有索引的顺序访问方法) 的缩写,它是存储记录和文件的标准方法.与其他存储引擎比较,MyISAM具有检查和修复表格的大多数工具. MyISAM表格可以被压缩,而且它们支持全文搜索.它们不是事务安全的,而且也不支持外键。如果事物回滚将造成不完全回滚，不具有原子性。如果执行大量的SELECT，MyISAM是更好的选择。  </p>
<p>InnoDB:这种类型是事务安全的.它与BDB类型具有相同的特性,它们还支持外键.InnoDB表格速度很快.具有比BDB还丰富的特性,因此如果需要一个事务安全的存储引擎,建议使用它.如果你的数据执行大量的INSERT或UPDATE,出于性能方面的考虑，应该使用InnoDB表,  </p>
<p>对于支持事物的InnoDB类型的标，影响速度的主要原因是AUTOCOMMIT默认设置是打开的，而且程序没有显式调用BEGIN 开始事务，导致每插入一条都自动Commit，严重影响了速度。可以在执行sql前调用begin，多条sql形成一个事物（即使autocommit打开也可以），将大大提高性能。  </p>
<p>===============================================================  </p>
<p>InnoDB和MyISAM是在使用MySQL最常用的两个表类型，各有优缺点，视具体应用而定。下面是已知的两者之间的差别，仅供参考。  </p>
<p>innodb<br />
InnoDB 给 MySQL 提供了具有事务(commit)、回滚(rollback)和崩溃修复能力 (crash recovery capabilities)的事务安全(transaction-safe (ACID compliant))型表。 InnoDB 提供了行锁(locking on row level)，提供与 Oracle 类型一致的不加锁读取(non- locking read in SELECTs)。这些特性均提高了多用户并发操作的性能表现。在InnoDB表中不需要扩大锁定 (lock escalation)，因为 InnoDB 的列锁定(row level locks)适宜非常小的空间。 InnoDB 是 MySQL 上第一个提供外键约束(FOREIGN KEY constraints)的表引擎。  </p>
<p>InnoDB 的设计目标是处理大容量数据库系统，它的 CPU 利用率是其它基于磁盘的关系数据库引擎所不能比的。在技术上，InnoDB 是一套放在 MySQL 后台的完整数据库系统，InnoDB 在主内存中建立其专用的缓冲池用于高速缓冲数据和索引。 InnoDB 把数据和索引存放在表空间里，可能包含多个文件，这与其它的不一样，举例来说，在 MyISAM 中，表被存放在单独的文件中。InnoDB 表的大小只受限于操作系统的文件大小，一般为 2 GB。<br />
InnoDB所有的表都保存在同一个数据文件 ibdata1 中（也可能是多个文件，或者是独立的表空间文件）,相对来说比较不好备份，免费的方案可以是拷贝数据文件、备份 binlog，或者用 mysqldump。  </p>
<p>MyISAM<br />
MyISAM 是MySQL缺省存贮引擎 .  </p>
<p>每张MyISAM 表被存放在三个文件 。frm 文件存放表格定义。 数据文件是MYD (MYData) 。 索引文件是 MYI (MYIndex) 引伸。  </p>
<p>因为MyISAM相对简单所以在效率上要优于InnoDB..小型应用使用MyISAM是不错的选择.  </p>
<p>MyISAM表是保存成文件的形式,在跨平台的数据转移中使用MyISAM存储会省去不少的麻烦  </p>
<p>以下是一些细节和具体实现的差别：  </p>
<p>1.InnoDB不支持FULLTEXT类型的索引。<br />
2.InnoDB 中不保存表的具体行数，也就是说，执行select count(*) from table时，InnoDB要扫描一遍整个表来计算有多少行，但是MyISAM只要简单的读出保存好的行数即可。注意的是，当count(*)语句包含 where条件时，两种表的操作是一样的。<br />
3.对于AUTO_INCREMENT类型的字段，InnoDB中必须包含只有该字段的索引，但是在MyISAM表中，可以和其他字段一起建立联合索引。<br />
4.DELETE FROM table时，InnoDB不会重新建立表，而是一行一行的删除。<br />
5.LOAD TABLE FROM MASTER操作对InnoDB是不起作用的，解决方法是首先把InnoDB表改成MyISAM表，导入数据后再改成InnoDB表，但是对于使用的额外的InnoDB特性（例如外键）的表不适用。  </p>
<p>另外，InnoDB表的行锁也不是绝对的，如果在执行一个SQL语句时MySQL不能确定要扫描的范围，InnoDB表同样会锁全表，例如 update table set num=1 where name like “%aaa%”  </p>
<p>任何一种表都不是万能的，只用恰当的针对业务类型来选择合适的表类型，才能最大的发挥MySQL的性能优势。  </p>
<p>===============================================================  </p>
<p>以下是InnoDB和MyISAM的一些联系和区别！  </p>
<p>1. 4.0以上mysqld都支持事务，包括非max版本。3.23的需要max版本mysqld才能支持事务。  </p>
<p>2. 创建表时如果不指定type则默认为myisam，不支持事务。<br />
可以用 show create table tablename 命令看表的类型。  </p>
<p>2.1 对不支持事务的表做start/commit操作没有任何效果，在执行commit前已经提交，测试：<br />
执行一个msyql：  </p>
<pre class="brush: sql; title: ; notranslate">
use test;  
drop table if exists tn;  
create table tn (a varchar(10)) type=myisam;  
drop table if exists ty;  
create table ty (a varchar(10)) type=innodb;  
 
begin;  
insert into tn values('a');  
insert into ty values('a');  
select * from tn;  
select * from ty;  
</pre>
<p>都能看到一条记录  </p>
<p>执行另一个mysql：  </p>
<pre class="brush: sql; title: ; notranslate">
use test;  
select * from tn;  
select * from ty;
</pre>
<p>只有tn能看到一条记录<br />
然后在另一边  </p>
<pre class="brush: sql; title: ; notranslate">
commit;  
</pre>
<p>才都能看到记录。  </p>
<p>3. 可以执行以下命令来切换非事务表到事务（数据不会丢失），innodb表比myisam表更安全：  </p>
<pre class="brush: sql; title: ; notranslate">
   alter table tablename type=innodb;  
</pre>
<p>3.1 innodb表不能用repair table命令和myisamchk -r table_name<br />
但可以用check table，以及mysqlcheck [OPTIONS] database [tables]  </p>
<p>==============================================================  </p>
<p>mysql中使用select for update的必须针对InnoDb，并且是在一个事务中，才能起作用。  </p>
<p>select的条件不一样，采用的是行级锁还是表级锁也不一样。</p>
<p>由于InnoDB 预设是Row-Level Lock，所以只有「明确」的指定主键，MySQL 才会执行Row lock (只锁住被选取的资料例) ，否则MySQL 将会执行Table Lock (将整个资料表单给锁住)。  </p>
<p>举个例子:  </p>
<p>假设有个表单products ，里面有id 跟name 二个栏位，id 是主键。  </p>
<p>例1: (明确指定主键，并且有此笔资料，row lock)  </p>
<pre class="brush: sql; title: ; notranslate">
SELECT * FROM products WHERE id='3' FOR UPDATE;  
</pre>
<p>例2: (明确指定主键，若查无此笔资料，无lock)  </p>
<pre class="brush: sql; title: ; notranslate">
SELECT * FROM products WHERE id='-1' FOR UPDATE;  
</pre>
<p>例2: (无主键，table lock)  </p>
<pre class="brush: sql; title: ; notranslate">
SELECT * FROM products WHERE name='Mouse' FOR UPDATE;  
</pre>
<p>例3: (主键不明确，table lock)  </p>
<pre class="brush: sql; title: ; notranslate">
SELECT * FROM products WHERE id&lt;&gt;'3' FOR UPDATE;  
</pre>
<p>例4: (主键不明确，table lock)  </p>
<pre class="brush: sql; title: ; notranslate">
SELECT * FROM products WHERE id LIKE '3' FOR UPDATE;  
</pre>
<p>注1:<br />
FOR UPDATE 仅适用于InnoDB，且必须在交易区块(BEGIN/COMMIT)中才能生效。</p>
<p>1.InnoDB table优点<br />
  硬件故障导致的server crash（比如停电），在下次重起database会自动恢复。<br />
  由InnoDB buffer pool 负责cache被访问的表和索引数据，直接在内存中进行处理，根据合理算法来保持热点块（hot）保留在内存中，极大地提高访问效率，减少I/O。<br />
  使用外健来实现参考完整性，实现数据的逻辑分割，同时还可以实现关联更新。<br />
  如果数据损坏，checksum机制能够在你使用时候提醒你这些受损的数据。<br />
  建议所有的表都有主健（频繁使用的field上或者auto_increment field上创建），这将极大提高基于where条件为主健（primary key）上的查询性能，包括order by , group by 等。<br />
  提供change buffering自动优化机制来优化诸如Insert,Update,Delete等操作；InnoDb能允许同一表上的读，写操作，还能cache 改变数据来减少I/O.</p>
<p>2.InnoDB table最佳处理方法<br />
  给每个InnoDB表指定主健<br />
  为提高组合查询性能，定义外健在join columns上，并且定义为相同数据类型，外健能实现因主表更新而关联更新子表，并且阻止子表的插入新数据，当这些新数据并不在主表存在时。<br />
  改变autocommit默认方式为不自动提交，减少提交次数过多带来的性能影响；可以由start transaction and commit来以&#8221;逻辑事务处理&#8221;等为单位来控制提交次数。<br />
  停止使用lock table语句，InnoDB能处理同一表上的读写并发sessions,并且不存在可靠性和性能损失。<br />
  Enable innodb_file_per_table开关，分开表空间存放数据，避免巨型系统表空间出现；同时为诸如压缩和fast truncate 等操作提供基础。<br />
  根据应用实际情况，进行表压缩，这不会影响该表的读写能力。<br />
  如果建表时指定engine= 子句存在问题，使用-sql_mode=no_engine_substitution来阻止表以其它存储引擎创建。</p>
<p>3.InnoDB相对与InnoDB Plugin时期的改变<br />
  可以压缩表和与之关联的索引<br />
  创建和删除索引比拥有以前更少的性能影响<br />
  Truncate表非常快，并且释放空间给操作系统使用；而针对系统表空间的truncate之后只能由innodb来使用。<br />
  存储BLOGs 和Long Text fields更有效率<br />
  增件新的针对storage engine内部工作的的系统表在information_schema 下<br />
  在performance_schema(新增的 db) 增加性能统计信息表<br />
  表有了更大的性能提升</p>
<p>4.性能提升<br />
  Crash recovery中，自动恢复到数据库一直状态，这过程快速而且值得信任。而且数据越大效果越明显。这相比过去来说由非常明显的提升。<br />
  大部分新的特性都是自动实现，并不需要额外的配置。详细的配置参考文档。</p>
<p>5.验证InnoDB在系统的状态<br />
  使用命令 SHOW VARIABLES LIKE &#8216;have_innodb&#8217;; 如果是NO,表示没有支持InnoDB,如果是DISABLED，则看是否配置中有skip-innodb选项，需要去掉。如果支持如下</p>
<pre class="brush: sql; title: ; notranslate">
     mysql&gt; show variables like 'have_i%';
     +---------------+-------+
     | Variable_name | Value |
     +---------------+-------+
     | have_innodb   | YES   |
     +---------------+-------+
     1 row in set (0.00 sec)
</pre>
<p>  使用命令SHOW ENGINES；能看到不同存储引擎，如果DEFAULT在innodb，代表支持并且为默认存储引擎。</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>解决MySQL 服务器进程CPU占用100%</title>
		<link>https://www.mudbest.com/%e8%a7%a3%e5%86%b3%e4%b8%80%e4%b8%aamysql-%e6%9c%8d%e5%8a%a1%e5%99%a8%e8%bf%9b%e7%a8%8bcpu%e5%8d%a0%e7%94%a8100/</link>
		
		<dc:creator><![CDATA[hkshadow]]></dc:creator>
		<pubDate>Tue, 21 Jun 2011 14:40:37 +0000</pubDate>
				<category><![CDATA[Mysql]]></category>
		<category><![CDATA[索引]]></category>
		<guid isPermaLink="false">http://www.mudbest.com/?p=681</guid>

					<description><![CDATA[MYSQL CPU 占用 100% 的解决过程 进入 mysql 的 shell 命令行，调用 show pr ... <a title="解决MySQL 服务器进程CPU占用100%" class="read-more" href="https://www.mudbest.com/%e8%a7%a3%e5%86%b3%e4%b8%80%e4%b8%aamysql-%e6%9c%8d%e5%8a%a1%e5%99%a8%e8%bf%9b%e7%a8%8bcpu%e5%8d%a0%e7%94%a8100/" aria-label="阅读 解决MySQL 服务器进程CPU占用100%">阅读更多</a>]]></description>
										<content:encoded><![CDATA[<p>MYSQL CPU 占用 100% 的解决过程</p>
<p>进入 mysql 的 shell 命令行，调用 show processlist, 查看当前 mysql 使用频繁的 sql 语句：</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; show processlist;
</pre>
<p>反复调用此命令，发现网站 A 的两个 SQL 语句经常在 process list 中出现，其语法如下：<span id="more-681"></span></p>
<pre class="brush: plain; title: ; notranslate">
SELECT t1.pid, t2.userid, t3.count, t1.date
FROM _mydata AS t1 
LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid
LEFT JOIN _mydata_body AS t2 ON t1.pid=t3.pid
ORDER BY t1.pid
LIMIT 0,15
</pre>
<p>调用 show columns 检查这三个表的结构 :</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; show columns from _myuser;
mysql&gt; show columns from _mydata;
mysql&gt; show columns from _mydata_body;
</pre>
<p>终于发现了问题所在：_mydata 表，只根据 pid 建立了一个 primary key，但并没有为 userid 建立索引。而在这个 SQL 语句的第一个 LEFT JOIN ON 子句中：</p>
<pre class="brush: plain; title: ; notranslate">
LEFT JOIN _myuser AS t3 ON t1.userid=t3.userid
</pre>
<p>_mydata 的 userid 被参与了条件比较运算。于是我为给 _mydata 表根据字段 userid 建立了一个索引：</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; ALTER TABLE `_mydata` ADD INDEX ( `userid` )
</pre>
<p>建立此索引之后，CPU 马上降到了 80% 左右。看到找到了问题所在，于是检查另一个反复出现在 show processlist 中的 sql 语句：</p>
<pre class="brush: sql; title: ; notranslate">
SELECT COUNT(*)
FROM _mydata AS t1, _mydata_key AS t2
WHERE t1.pid=t2.pid and t2.keywords = '孔雀'
</pre>
<p>经检查 _mydata_key 表的结构，发现它只为 pid 建了了 primary key, 没有为 keywords 建立 index。_mydata_key 目前有 33 万条记录，在没有索引的情况下对33万条记录进行文本检索匹配，不耗费大量的 cpu 时间才怪。看来就是针对这个表的检索出问题了。于是同样为 _mydata_key 表根据字段 keywords 加上索引:</p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; ALTER TABLE `_mydata_key` ADD INDEX ( `keywords` )
</pre>
<p>建立此索引之后，CPU立刻降了下来，在 50%~70%之间震荡。<br />
再次调用 show prosslist，网站A 的sql 调用就很少出现在结果列表中了。但发现此主机运行了几个 Discuz 的论坛程序， Discuz 论坛的好几个表也存在着这个问题。于是顺手一并解决，cpu占用再次降下来了。</p>
<p>注(mysql查询条件简单介绍)：</p>
<p>对 WHERE, JOIN, MAX(), MIN(), ORDER BY 等子句中的条件判断中用到的字段,应该根据其建立索引 INDEX。索引被用来快速找出在一个列上用一特定值的行。没有索引，MySQL不得不首先以第一条记录开始并然后读完整个表直到它找出相关的行。表越大，花费时间越多。如果表对于查询的列有一个索引，MySQL能快速到达一个位置去搜寻到数据文件的中间，没有必要考虑所有数据。如果一个表有1000行，这比顺序读取至少快100倍。所有的MySQL索引(PRIMARY、UNIQUE和INDEX)在B树中存储。</p>
<p>索引 index 用于：<br />
快速找出匹配一个WHERE子句的行<br />
当执行联结(JOIN)时，从其他表检索行。<br />
对特定的索引列找出MAX()或MIN()值<br />
如果排序或分组在一个可用键的最左面前缀上进行(例如，ORDER BY key_part_1,key_part_2)，排序或分组一个表。如果所有键值部分跟随DESC，键以倒序被读取。<br />
在一些情况中，一个查询能被优化来检索值，不用咨询数据文件。如果对某些表的所有使用的列是数字型的并且构成某些键的最左面前缀，为了更快，值可以从索引树被检索出来。</p>
<p>假定你发出下列SELECT语句： </p>
<pre class="brush: plain; title: ; notranslate">
mysql&gt; SELECT * FROM tbl_name WHERE col1=val1 AND col2=val2;
</pre>
<p>如果一个多列索引存在于col1和col2上，适当的行可以直接被取出。如果分开的单行列索引存在于col1和col2上，优化器试图通过决定哪个索引将找到更少的行并来找出更具限制性的索引并且使用该索引取行。</p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
