<?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>ChenTaoqian&#039;s Blog &#187; 数据库</title>
	<atom:link href="http://www.chentaoqian.com/archives/tag/database/feed" rel="self" type="application/rss+xml" />
	<link>http://www.chentaoqian.com</link>
	<description>主机,企业邮箱,域名,空间,服务器,Java,Oracle,PHP,Linux,JS,MySQL,Apache</description>
	<lastBuildDate>Wed, 30 Nov 2011 14:35:01 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Mysql的排序机制</title>
		<link>http://www.chentaoqian.com/archives/582</link>
		<comments>http://www.chentaoqian.com/archives/582#comments</comments>
		<pubDate>Sun, 02 May 2010 05:26:06 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[原理]]></category>
		<category><![CDATA[排序]]></category>
		<category><![CDATA[数据库]]></category>
		<category><![CDATA[机制]]></category>

		<guid isPermaLink="false">http://www.chentaoqian.com/?p=582</guid>
		<description><![CDATA[在查mysql的排序问题时， 了解了一下Mysql的排序机制， 大体是：
mysql把需要排序的地方都叫filesort， 名字上看有个file在里面，但不一定与文件有关， 可能就是在内存完成的排序。
MySQL 有二个 filesort 算法， 第一个方法(原始方法)只使用了ORDER BY中指定的字段。第二个方法(改进的方法)不仅使用ORDER BY中指定的字段，还是用了查询中所涉及到的所有的字段。
优化器决定选择哪个filesort 算法， 除了查询中涉及到TEXT或者BLOCk字段外，它通常使用改进的算法，当查询中涉及到TEXT或者BLOCk字段时，通常使用原始的方法。
原始的 filesort 算法的工作机制大体是(典型的外排算法)：
1.   通过主键扫描或表扫描读出所有的数据记录，不相配WHERE条件的记录被跳过。
2.   对于每条记录，储存一对信息（主键和指向记录的指针）到查询缓冲区，缓冲区的大小是 sort_buffer_size 系统变量控制的。
3.   一旦缓冲区满了，对缓冲区中的数据做一次 qsort（快速排序）并把排序结果保存到一个临时文件。（如果所有记录信息能放到缓冲区中，就没有必要存到临时文件了)
4.   重复前述的步骤直到所有的记录都处理了完。
5.   每在合并缓冲区中做多路合并， 并把合并后的结果输出到另外一个临时文件
6.   重复多路合并排序， 直到所有的记录信息能分到15个以内的有序集合。
7.   在最后多路合并中，只有指向记录的指针被写到一个结果文件。
8.   根据结果文件中的记录指针的读取出记录放到返回集合中， 这个结果缓冲区的大小是 read_rnd_buffer_size 系统变量设置的。
这个排序算法有几个问题值得注意：
1. 它需要读取记录两次：第一次是执行的WHERE时候，第二次是在对key进行排序之后。 尽管第一次是读取时记录是连续读取的（比如表扫描）, 第二次就是随机读取了。（这时候键值是有序的了，但是记录还不是)
2. 使用到了快速排序，也就是说，排序结果是不稳定的
改进的 filesort 算法在原始的算法的基础上做了一些优化： 在排序时，不只是对键值进行操作，还带有记录位置和查询中需要的字段信息，这避免两次都记录。改进的 filesort [...]]]></description>
		<wfw:commentRss>http://www.chentaoqian.com/archives/582/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Mysql主从同步延迟受到机器系统时间的影响</title>
		<link>http://www.chentaoqian.com/archives/569</link>
		<comments>http://www.chentaoqian.com/archives/569#comments</comments>
		<pubDate>Sat, 01 May 2010 00:42:22 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[同步]]></category>
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://www.chentaoqian.com/?p=569</guid>
		<description><![CDATA[Mysql主从同步延迟受到多种因素影响， 比如大事务， 从库查询压力， 网路延迟等； 这些比较常见； 但还受到主从机器系统时钟差的影响，这一点可能容易被忽视。
上周， 就遇到了这样的情况， 主库的系统时间由于某种原因落后于从库几十秒， 结果频繁的出现大的主从延迟同步 ，查了N久业务方面的问题， 都找不出原因； 在和同事的交流中，发现大家对参数Seconds_Behind_Master的理解有点补一样，基本有两种理解：
一种理解是来源于Mysql手册上的描述， 大体意思是这个时间是从库SQL线程处理的最近的日志事件的时间戳减去从库IO线程处理的最近一条日志记录的时间戳得到的, 可以简单理解为从库SQL线程与IO线程所处理的最近的日志事件的时间戳差；这个计算方式给人的感觉不是在计算主从延迟，而是在计算从库上两个线程的处理 的日志的时差。
另一种理解来源于《High Performace Mysql》上的的描述， 大体意思这个参数反映的结果是当前系统时间减去从库IO线程所处理的最近一条日志记录的时间戳； 但这个说法有一个明显的不太让人信服的地方， 就是如果机器的系统时间相差比较大怎么办？ 显然， 如果系统时间相差比较大的话， 以这样的方式计算主从延迟毫无意义。
在有分歧的情况下， 去查看了一下Mysql的源代码， 结果发现手册上的描述居然不那么准确， 代码大致如下：
&#8230;&#8230;
if ((mi-&#62;slave_running == MYSQL_SLAVE_RUN_CONNECT) &#38;&#38;
mi-&#62;rli.slave_running)
{
long time_diff= ((long)(time(0) &#8211; mi-&#62;rli.last_master_timestamp)
- mi-&#62;clock_diff_with_master);
protocol-&#62;store((longlong)(mi-&#62;rli.last_master_timestamp ?
max(0, time_diff) : 0));
&#8230;&#8230;
}
else
{
protocol-&#62;store_null();
}
从代码看， 如果从库IO线程到主库的连接有问题或者SQL线程没有在运行， Seconds_Behind_Master直接返回NULL; 否则的话， 用从库当前系统时间减去IO线程处理的最近的事件的时间戳； 代码里用mi-&#62;clock_diff_with_master来排除系统时间差对计算的影响， 那这个值又是怎么计算来的呢？ 继续看代码：
&#8230;&#8230;
if (!mysql_real_query(mysql, STRING_WITH_LEN(&#8220;SELECT UNIX_TIMESTAMP()&#8221;)) &#38;&#38;
(master_res= mysql_store_result(mysql)) &#38;&#38;
(master_row= mysql_fetch_row(master_res)))
{
mi-&#62;clock_diff_with_master =  [...]]]></description>
		<wfw:commentRss>http://www.chentaoqian.com/archives/569/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL表设计优化与索引 (十)</title>
		<link>http://www.chentaoqian.com/archives/566</link>
		<comments>http://www.chentaoqian.com/archives/566#comments</comments>
		<pubDate>Wed, 28 Apr 2010 15:06:42 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://www.chentaoqian.com/?p=566</guid>
		<description><![CDATA[Bit-Packed Data Types
MySQL有一些存储类型使用一个值中的一些单个的比特位来紧凑的存储数据。纯技术上将，不管是底层的存储格式还是操作，所有这些类型都是字符串类型。
BIT
MySQL5.0以前， BIT只是TINYINT的同义词而已。但是在MySQL5.0以及之后的版本，BIT是一个完全不同的数据类型了， 有着自己的一些特点， 这里讨论一些新的行为和属性:
可以用BIT字段在单列里面来存储一个或多个true/false值， BIT(1)定义一个了只包含单个比特位的字段， BIT(2)是存储2个比特位的字段， 如此类推；BIT字段的最大长度可以是64个比特。
BIT类型的行为与存储引擎有关。MyISAM把一些列为了存储的目的打包到一起， 所以17个单独的BIT列需要17个比特来存储(假定这些列都不允许NULL)，MyISAM会近似算成3个字节来存储。其他的一些存储引擎， 比如Memory和InnoDB, 把每个列都用有足够长度存储这些比特位的最小整数来存储，所以无法节省存储空间。
* TIMESTAMP类型的一些行为的规则比较复杂并随着不同的MySQL版本而变化，所以在使用时应当确认是自己所期望的行为。通常， 在对TIMESTAMP的列做了改变后通过查看SHOW CREATE TABALE的结果来确认是一个的主意。
MySQL把BIT当做字符串类型， 而不是数据类型。当检索BIT(1)列的值， 结果是一个字符串而内容是二进制位0或1， 而不是ASCII值&#8221;0&#8243;或&#8221;1&#8243;.然而， 如果在一个数值上下文检索的话， 结果是比特串转化而成的数字。 当需要与另一个值进行比较时， 记住这一点。比如， 如果存储值&#8217;00111001&#8242;（是57的二进制表示）到一个BIT(8)的字段中然后检索出来，得到的是字符编码值为57字符串， 而这值就是“9”的ASCII编码。但是在数值环境中， 得到的是值57:s
mysql&#62; CREATE TABLE bittest(a bit(8));
mysql&#62; INSERT INTO bittest VALUES(b&#8217;00111001&#8242;);
mysql&#62; SELECT a, a + 0 FROM bittest;
+&#8212;&#8212;+&#8212;&#8212;-+
&#124; a &#124; a + 0 &#124;
+&#8212;&#8212;+&#8212;&#8212;-+
&#124; 9 &#124; 57 &#124;
+&#8212;&#8212;+&#8212;&#8212;-+
这非常容易引起混淆， 所以我们提醒小心使用BIT类型。对于大多数应用程序来说，避免使用这个类型比较的好。
如果想在单个比特位的存储空间中存储true/false值的另一个选择是使用可以为NULL的CHAR(0)列。这个列能够存储NULL和长度为0的空串。
SET
如果需要存储多个true/false的值， 可以考虑把多个列放到一个MySQL所支持的SET数据类型，而MySQL内部通过一些比特位来表示的。这种类型有效的使用存储空间， MySQL也有一些函数如FIND_IN_SET( )和FIELD( [...]]]></description>
		<wfw:commentRss>http://www.chentaoqian.com/archives/566/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL表设计优化与索引 (九)</title>
		<link>http://www.chentaoqian.com/archives/564</link>
		<comments>http://www.chentaoqian.com/archives/564#comments</comments>
		<pubDate>Tue, 27 Apr 2010 14:58:55 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://www.chentaoqian.com/?p=564</guid>
		<description><![CDATA[日期和时间类型
MySQL有多个表示各种日期和时间值的数据类型， 比如YEAR和DATE. MySQL存储时间的最精确粒度是秒。 然而， 能做微妙粒度的临时计算， 我们会列出一些绕过存储引擎限制的一些方法。
许多时间类型都没有可替换类型， 因而不存在什么是最佳选择这么一说。 唯一的问题是当需要一起存储日期和时间时如何做？MySQL提供了两个非常类似的数据类型来做这个事情: DATETIME和TIMESTAMP. 多大多数应用来说， 两个都行， 但是在某些场合， 一个可能比另一个更合适：
DATETIME
这个类型能够存储很大范围的值， 从1001年到9999年， 准确到秒的精度。它把日期和时间打包成整数以YYYYMMDDHHMMSS 格式表示， 与时区无关。用8个字节的存储空间。
缺省情况下， MySQL以可排序，无歧义的格式显示DATETIME值， 比如 2008-01-16 22:37:08, 这是ANSI下标准显示日期时间的方式。
TIMESTAMP
如名字所指出的，TIMESTAMP 类型存储从1970年1月1日(格林威治时间)到目前为止经过的秒数 &#8211;与UNIX时间戳一样。TIMESTAMP 使用4个字节来存储值， 所能表示的范围以比DATETIME要小: 从1970年到2038年。MySQL提供了 FROM_UNIXTIME( ) 和 UNIX_TIMESTAMP( ) 两个函数来进行Unix时间戳与日期类型的相互转换。
新版本的MySQL中TIMESTAMP 采用了与DATETIME 一样的格式来表示值，但是老版本的MySQL没有在各个部分件显示分隔符。 这只是一个显示格式的区别而已，TIMESTAMP 的存储格式在各个版本与DATETIME一致。
TIMESTAMP 对值的显示与时区相关，MySQL服务器，操作系统和客户端连接都有相应的时区设置。
因此，对于与GMT有5个小时时差的东部时间，一个值为0的TIMESTAMP 类型实际显示的内容可能会是1969-12-31 19:00:00。
TIMESTAMP 也有一些DATETIME所不具备的一些属性。 缺省情况下， 插入记录时，MySQL会把第一个没指定具体值得TIMESTAMP 类型的字段自动设置为当前值，在修改时， 如果没有在修改语句中显式的指定值， 第一个DATESTAMP类型的字段的值也会被更行为当前值。也可以通过配置修改修改和插入记录时对TIMESTAMP 列的处理行为。最后， TIMESTAMP列缺省不为NULL, 这与其他数据类型不一样。
除了一些特殊行为，在一般情况下，如果能够使用TIMESTAMP，就使用它， 因为它比DATETIME的空间效率要高。有时候，有人把Unix时间戳存储成整数， 但是实际上没有任何好处，因为格式转换很不方便，我们不推荐这么做。
如果需要存储比秒精度更高的日期和时间数据怎么办呢？MySQL当前并没有提供合适的数据类型， 但是可以根据需要选择自己的存储格式：可以使用BIGINT类型存储毫秒精度的数据，或者使用DOUBLE类型，把秒后面的数值当做小数点后面的小数部分。 这两种方法都不错。
]]></description>
		<wfw:commentRss>http://www.chentaoqian.com/archives/564/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL表设计优化与索引 (八)</title>
		<link>http://www.chentaoqian.com/archives/561</link>
		<comments>http://www.chentaoqian.com/archives/561#comments</comments>
		<pubDate>Mon, 26 Apr 2010 12:17:44 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://www.chentaoqian.com/?p=561</guid>
		<description><![CDATA[使用ENUM代替字符串类型
有时候， 可以通过使用ENUM来代理常规的字符串类型。一个ENUM列能够存储65535个不同的字符串值，MySQL非常紧凑的存储这些值，会根据值列表把这些值存储到1到2个字节中。通过在表的.frm文件中保存一个数字到字符串的对应关系来保存一个&#8221;查询表&#8221;， 它把每个值存储成一个表示值在字段定义列表中的某个位置的整数。 下面是几个例子;
mysql&#62; CREATE TABLE enum_test(
-&#62; e ENUM(&#8216;fish&#8217;, &#8216;apple&#8217;, &#8216;dog&#8217;) NOT NULL
-&#62; );
mysql&#62; INSERT INTO enum_test(e) VALUES(&#8216;fish&#8217;), (&#8216;dog&#8217;), (&#8216;apple&#8217;);
这3列实际上存储的是整数， 而不是字符串。 能够通过在数字检索上下文中查看到这些值的两面属性：
mysql&#62; SELECT e + 0 FROM enum_test;
+&#8212;&#8212;-+
&#124; e + 0 &#124;
+&#8212;&#8212;-+
&#124; 1 &#124;
&#124; 3 &#124;
&#124; 2 &#124;
+&#8212;&#8212;-+
如果指定数字当做ENUM常量的话， 这个两面性太容易引起混淆了。建议不要这么做。
另外一个令人奇怪的是ENUM字段通过整数值来排序， 而不是字符串本省：
mysql&#62; SELECT e FROM enum_test ORDER BY e;
+&#8212;&#8212;-+
&#124; e &#124;
+&#8212;&#8212;-+
&#124; fish &#124;
&#124; apple &#124;
&#124; dog &#124;
+&#8212;&#8212;-+
通过指定期望的ENUM数字的排序顺序来解决这个问题。也可以通过在查询中显式的使用FIELD()来指定排序顺序， [...]]]></description>
		<wfw:commentRss>http://www.chentaoqian.com/archives/561/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL表设计优化与索引 (七)</title>
		<link>http://www.chentaoqian.com/archives/558</link>
		<comments>http://www.chentaoqian.com/archives/558#comments</comments>
		<pubDate>Sun, 25 Apr 2010 15:00:12 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://www.chentaoqian.com/?p=558</guid>
		<description><![CDATA[如何避免磁盘临时表
因为内存储引擎不支持TEXT和BLOB数据类型， 使用到BLOB和TEXT列的查询和使用隐式临时表的查询将不得不使用MyISAM的磁盘临时表， 即使只有很少的几条记录。 这可能导致很严重的性能开销。即使把MySQL配置成在RAM盘上使用临时表， 也会用到一些开销大的系统调用(Maria存储引擎应该能通过把所有的东西， 而不只是索引，缓存在内存中而在一定程度上缓解这个问题)。最好的解决办法是避免使用BLOB和TEXT类型， 除非费用不可。
.
如果无法避免使用BLOB和TEXT类型， 应该能够通过使用ORDER BY SUBSTRING(column, length)
的办法来把这些类型的值转化成字符串，这样不会妨碍使用内存临时表。另外， 确认一下的所使用的子串的长度是否短到不会导致临时表的大小不会超过 max_heap_table_size 或 tmp_table_size， 否则，还是会生成MyISAM的磁盘临时表。
如果EXPLAIN结果中的&#8221;Extra&#8221;列里面包含&#8221;Using temporary&#8221;， 那么查询会使用一个隐式的临时表。
]]></description>
		<wfw:commentRss>http://www.chentaoqian.com/archives/558/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL表设计优化与索引 (六)</title>
		<link>http://www.chentaoqian.com/archives/555</link>
		<comments>http://www.chentaoqian.com/archives/555#comments</comments>
		<pubDate>Sat, 24 Apr 2010 12:16:50 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://www.chentaoqian.com/?p=555</guid>
		<description><![CDATA[BINARY和VARBINARY
数据的存储是存储引擎相关的， 并不是所有的存储引擎用同样的方式来处理定长和变长类型。Memory存储引擎使用定长的行， 因而它分配尽可能多的空间给变长字段来存储数据。 而Falcon则使用变长字段来存储， 即使对于CHAR字段也是如此。 但是填充和去尾是一致de 这是因为这个是由MySql服务器自己处理的。
CHAR和VCHAR的兄弟类型分别是存储二进制数据的BINARY和VARBINARY， 二进制字符串与普通的字符长相似， 不过他们是以字节存储的， 而不是字符，填充也不一样 ， Mysql用\0(0 字节)而不是空格填充二进制数据， 而在检索时不会把后面的填充值去掉。
对于需要存数二进制数据的活着需要Mysql对值进行字节的比较而不是基于字符的比较时， 二进制数据类型非常有用。基于字节的比较的优势不只是大小写不敏感的好处， Mysql在比较二进制数据时， 通过字节表示的数值比较的方式进行的， 因为二进制数据相对与基于字符的比较更简单， 也更快。
]]></description>
		<wfw:commentRss>http://www.chentaoqian.com/archives/555/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL表设计优化与索引 (五)</title>
		<link>http://www.chentaoqian.com/archives/552</link>
		<comments>http://www.chentaoqian.com/archives/552#comments</comments>
		<pubDate>Fri, 23 Apr 2010 15:48:45 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://www.chentaoqian.com/?p=552</guid>
		<description><![CDATA[当存储一个CHAR值时， Mysql会除去尾随空间,  这个行为有点让人困惑， 用一个具体的例子来看一下： 首先 ，创建一个只有一个CHAR(10)字段的表并存储一些值在里面：
mysql&#62; CREATE TABLE char_test( char_col CHAR(10));
mysql&#62; INSERT INTO char_test(char_col) VALUES
-&#62; (&#8217;string1&#8242;), (&#8216; string2&#8242;), (&#8217;string3 &#8216;);
然后检索这些值， 尾部空间被除掉了：
mysql&#62; SELECT CONCAT(&#8220;&#8216;&#8221;, char_col, &#8220;&#8216;&#8221;) FROM char_test;
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+
&#124; CONCAT(&#8220;&#8216;&#8221;, char_col, &#8220;&#8216;&#8221;) &#124;
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+
&#124; &#8217;string1&#8242; &#124;
&#124; &#8216; string2&#8242; &#124;
&#124; &#8217;string3&#8242; &#124;
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+

如果存储同样的值在VARCHA（10）的字段里， 在检索的时候得到的结果如下：
mysql&#62; SELECT CONCAT(&#8220;&#8216;&#8221;, varchar_col, &#8220;&#8216;&#8221;) FROM varchar_test;
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+
&#124; CONCAT(&#8220;&#8216;&#8221;, varchar_col, &#8220;&#8216;&#8221;) &#124;
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+
&#124; &#8217;string1&#8242; &#124;
&#124; &#8216; string2&#8242; &#124;
&#124; [...]]]></description>
		<wfw:commentRss>http://www.chentaoqian.com/archives/552/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL表设计优化与索引 (四)</title>
		<link>http://www.chentaoqian.com/archives/547</link>
		<comments>http://www.chentaoqian.com/archives/547#comments</comments>
		<pubDate>Thu, 22 Apr 2010 13:32:43 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://www.chentaoqian.com/?p=547</guid>
		<description><![CDATA[String Types(字符串类型)
字符串类型
Mysql支持多种字符串类型的变体。 这些数据类型在4.1和5.0版本中有较大的变化， 这使得这些数据类型变得更加复杂。 从Mysql4.1起， 每个字符串类型能有自己的字符集和针对这些字符集的排序规则集 （更多的关于排序规则的主题， 参考第5章）， 这对于性能有较大的影响。
VARCHAR和CHAR类型
VARCHAR和CHAR是两种最主要的存储字符串的数据类型， 不幸的是，的确有些困难解释这两种数据类型在磁盘和内存中是如何存储的，  因为这是与存储引擎相关的(比如， Falcon的差不多所有数1是， 请参考相应的存储引擎文档。
先看看VARCHAR和CHAR值的典型的磁盘存储方式。 同一种存储引擎对VARCHAR和CHAR在磁盘和内存中的存储格式可能是不一样的， 当从一个地方读取并存到另一个地方时， 服务器可能需要做一些转换工作。 两种数据类型的一些比较：
VARCHAR存储可变长度的字符串， 它应该是最为常见的数据类型了。 相对于固定长度的数据类型， 它需要的存储恐空间相对较少， 因为它按需分配存储空间 (比如， 存储短字符串的时候就用少的空间). 例外的地方在MyISAM中建立ROW_FORMAT=FIXED的表， 这种表对于每一行都使用相同数量空间来存储， 因而会导致空间浪费。VARCHAR 使用1或2个字节来记录值的长度: 如果字段的长度小于255个字节， 用1个字节， 否则用2个字节。假定使用latin1字符集， 一个VARCHAR(10)的字段值使用11个字节的存储空间， 1个VARCHAR(1000)的字段值使用1002字节的空间， 因为需要2个字节来存储长度信息。
VARCHAR有助于改善性能， 因为能节省空间。 但是， 因为记录的长度是可变的， 当修改的时候因为记录可能变长会导致一些额外的工作。 如果一列增长了而原来的存储空间不能存储修改后的值， 具体的增长策略是与具体的存储引擎相关的。 比如， MyISAM可能导致分行， 而innodb则可能会导致分页来处理。 其他的一些引擎则可能不会在原来的地方修改数据。
一般来说， 当某个字段的最大长度远远大于平均长度时； 或者很少修改字段因为碎片化不会是一个问题； 或者使用一个复杂的字符集合比如UTF-8, 而每个字符使用变长的字节来表示时， 使用VARCHAR来存储时值得的。
CHAR是固定长度的， Mysql总是分配足够的空间来存储指定数目的字符。当存储一个CHAR值时， Mysql会除去尾随空间(在4.1以及之前的版本， VARCHAR也是这么处理的， VARCHAR和CHAR逻辑上市一样的，只是存储格式不一样而已.) 当比较时， 字段后面会根据需要垫加一些空格来进行比较。
当需要存储非常短的字符串时； [...]]]></description>
		<wfw:commentRss>http://www.chentaoqian.com/archives/547/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>MySQL表设计优化与索引 (三)</title>
		<link>http://www.chentaoqian.com/archives/541</link>
		<comments>http://www.chentaoqian.com/archives/541#comments</comments>
		<pubDate>Wed, 21 Apr 2010 13:19:43 +0000</pubDate>
		<dc:creator>admin</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[优化]]></category>
		<category><![CDATA[数据库]]></category>

		<guid isPermaLink="false">http://www.chentaoqian.com/?p=541</guid>
		<description><![CDATA[Real Numbers
实数
实数是具有小数部分的数字， 当然， 实数不是专门用来表示小数的， 也可以用DECIMAL来存储那些无法用INTERGER来存储的大整数。 Mysql同时支持准确的和非准确的类型。
FLOAT和DOUBLE类型支持近似的标准浮点数数学计算。 如果需要知道准确的浮点数计算， 参考具体平台的浮点数计算规则。
DECIMAL类型是用来存储准确的小数， 在mysql 5.0以后的版本， DECIMAL支持准确的数学计算。在Mysql4.1 及以前的版本中， MUMERIC类型也是用浮点计算来完成运算的， 因此可能会出现一些由于精度损失而出现的一些不准确的结果， 在这些版本的mysql中， DECIMAL是一种&#8221;存储&#8221;概念类型。
在5.0以及以后的版本， mysql自己来进行DECIMAl计算， 因为cpu没有对DECIMAL的直接支持。 当然， 浮点计算在某种程度上相对快些， 因为CPU是直接支持浮点计算的。

浮点类型和DECIMAl类型允许指定精度。对于DECIMAL字段， 能够指定小数点前和后允许的最多的数字个数， 这个关系到数值的存储空间的消耗。Mysql5.0以及以后的版本中， 所有的数字位数以二进制字符串的方尺存储的(每4个字节9个数字）。 例如， DECIMAL（18， 9） 数据类型的小数点两边都存储9个数字符号， 因此共用9个字节， 4个字节存储小数点之前的数字符号， 1个字节存储小数点本身， 4个字节存储小数点之后的数字符号。
在MYSQL 5.0及之后的版本， 一个DECIMAL数字能存储65位数字， 早期的mysql版本有254位数字的限制， 并把数字打包存储成字符串(每个数字一个字节)。 在运算中， 这些版本的mysql一般不需要使用到这么多的空间， 因为DECIMAL只是表示存储格式， 在计算中是通过转换成DOUBLE类型的数字来进行的。有多种方式指定浮点类型字段需要的精确度， 这使得Mysql会悄悄的选择另外一种不同的数据类型或近似值来存储。 这些精确度修饰符不是标准的， 所以建议通过选择数据类型而不是精度。
一般情况下， 存储相同范围数值的浮点数类型比DECIMAL类型所使用的空间要小些； 1个FLOAT字段用4个字节的存储，DOUBLE用8个字节的来存储更高精度和更大范围的数值。 其实对于整数类型来说， INTERGER指定的其实是存储类型， mysql其实用的是DOUBLE来进行存储和内部计算的。 因为DECIMAL需要占更多的存储空间和需要更多的计算资源， 因此除非在一些需要准确计算结果的场合&#8211;比如存储财务数据外， 尽量不是使用。
未完待续
]]></description>
		<wfw:commentRss>http://www.chentaoqian.com/archives/541/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

