aus*_*nbv 7 mysql sql database performance
我已经研究和阅读了几天的SQL数据类型(我知道......我知道,这不是很长)而且我很难掌握的一个问题是如何选择最佳数据类型可扩展性,效率和易用性.
我认为如何选择基本数据类型(即int vs varchar)非常简单,但是如何在blob和文本类型之间做出选择.
MySQL手册页很棒,但它们不是我们计算机爱好者所喜欢的...高效.
我认为如果我们可以编译一个MySQL数据类型列表,每个数据类型的一般优点/缺点以及何时选择该数据类型是有意义的,那将是非常棒的.
Iso*_*opp 11
MySQL字符串类型有两种变体:一种没有字符集标签,另一种带有字符集标签.
固定长度的字符串,在末尾填充空格,是CHAR(n).没有字符集标签的匹配类型是BINARY(n).在一个存储字符串"hello" CHAR(255) CHARSET utf8将765个字节的(字符串用空格全长填补,存储为UTF8其作为3个字节的最坏情况下的空间的使用/字符分配3个*255字节).
具有一个或两个长度字节且没有填充的可变长度字符串是VARCHAR((n).没有字符集标签的匹配类型是VARBINARY(n).在a中存储字符串"hello" VARCHAR(255) CHARSET utf8将占用6个字节(1个长度)字节加上实际文本的5个字节..将字符串クリス存储在同一类型中将需要10个字节(1个长度字节加上3个字符,每个字符使用3个字节来表示它们).
mysql> select hex('???'), length(hex('???'))/2 as bytes;
+--------------------+--------+
| hex('???') | bytes |
+--------------------+--------+
| E382AFE383AAE382B9 | 9.0000 |
+--------------------+--------+
1 row in set (0.02 sec)
Run Code Online (Sandbox Code Playgroud)
具有一个,两个,三个或四个长度字节的可变长度字符串是TINYTEXT,TEXT,MEDIUMTEXT和LARGETEXT.没有字符集标签的匹配类型是TINYBLOB,BLOB,MEDIUMBLOB和LARGEBLOB.
类似TEXT/BLOB的类型与VARCHAR/VARBINARY类型的不同之处在于数据的存储方式和位置,请参阅http://www.mysqlperformanceblog.com/2010/02/09/blob-storage-in-innodb/有关如何在InnoDB中存储类似TEXT/BLOB类型的详细信息,具体取决于版本和ROW_FORMAT设置.出于性能原因,您需要最新版本的InnoDB和"Barracuda"-Format表.
除非您在服务器端构造复杂且内存密集的变通方法,否则MySQL无法处理大于max_allowed_packet(默认值:1M)的任何数据.这进一步限制了类似TEXT/BLOB的类型可以做什么,并且通常使LARGETEXT/LARGEBLOB类型在默认配置中无用.
对于没有字符集标签的类型(BINARY,VARBINARY和%BLOB%),MySQL将接收收到的数据并将其写入磁盘.对于具有字符集标签的类型,MySQL将查看您宣布为服务器的客户端字符集SET NAMES以及列定义的字符集标签的内容.然后它将从连接字符集转换为列字符集并写入转换后的数据.您可以使用HEX()函数检查,例如SELECT HEX(str) FROM t WHERE id = ....
在检索时,宣布的字符集连接SET NAMES可能与写入时的连接不同.MySQL将再次针对为此连接声明的字符集检查列字符集标签,如有必要,将转换为连接字符集.
无论如何,与此类数据产生的磁盘I/O所花费的时间相比,该转换的性能损失可以忽略不计,从性能上讲,几乎不管您选择哪种类型.相反,规则是:如果您正在使用文本数据,请选择带有字符集标签的类型,如果不使用,则选择不带类型的类型.
经常会问一个相关的问题:我应该选择CHAR或VARCHAR(分别是BINARY还是VARBINARY)?
对于InnoDB,答案总是:选择可变长度数据类型.InnoDB中的固定长度数据类型没有任何性能优势,但是如果您选择固定长度的数据类型然后不使用其中的所有空间,则存在巨大的尺寸损失.加上固定长度的SQL字符串类型有关于填充和修剪的最终规则非常奇怪,最后你可能不会费心去学习.对于MySQL,情况可能不同,但几乎从来没有.
另一个相关的问题:我应该为我的字符串选择VARCHAR或TEXT(分别是VARBINARY或BLOB)?
答案是使用最新版本的InnoDB,Barracuda格式表,然后是TEXT/BLOB.其原因在http://www.mysqlperformanceblog.com/2011/04/07/innodb-row-size-limitation/中详细解释.其结果是:使用前Barracuda格式的VARCHAR或TEXT/BLOB,如果在一行中有太多的InnoDB行大小限制,则存在溢出InnoDB行大小限制的风险.
最后:我应该将文件/图像/其他大型blob或文本数据存储在数据库中吗?
答案是:通常不是.与从文件系统提供文件相比,从数据库(http://mysqldump.azundris.com/archives/36-Serving-Images-From-A-Database.html)提供文件是一项昂贵的操作.如果可能的话,你会想要这样做.有一种解决方法,http://www.blobstreaming.org/,但这是一种先进的技术,要求您完全控制您的执行环境,这在托管环境中绝不是这种情况.
解决此问题:MEMORY引擎表中没有可变长度数据类型.因此,如果您在EXPLAIN输出中看到"使用临时" ,这意味着
如果此进程的临时表变得大于tmp_table_size或max_heap_table_size,则它将被动态转换为MyISAM格式并转到磁盘.
示例:您正在定义一个Ruby Active Record类User,其中包含十个标记为的字段:string.这些中的每一个最终都VARCHAR(255) CHARSET utf8在你的Users桌子里.
在您的代码库中的其他地方,Users正以涉及计划的方式使用using temporary.您在加载时立即死于磁盘操作,因为Users表中的每一行现在至少在MEMORY中使用7650个字节,其中大部分是用作填充的空格.这会强制将临时表转换为MyISAM并写入磁盘.
这意味着需要重写具有TEXT或BLOB类型的任何查询以及具有"using temporary"的计划,以避免临时表命中磁盘.