用自增INT字段做主键应该是效率最高的。现在的情况是这样的: - C程序在写MySQL数据库时,同时会在内存中缓存一定时间的内记录 - 有个关联引擎会对这些记录进行关联运算,关联运算可能生成新的所谓关联记录 - 关联记录有可能被更新(新进来的记录匹配以前的关联) - 数据库暂时连不上时希望能先在本地硬盘进行缓存,然后不断重试连接数据库 - 希望关联引擎与写数据库的模块分别由两个独立的线程完成基于以上考虑,希望能由C程序自己生成主键的值。比较靠谱的方法是生成36个字节的UUID(类似c2ece7c0-5ca1-11df-a08a-0800200c9a66),它的唯一性不受进程重启,机器重启等的影响。现在的问题是用这种36字节的UUID做主键,会不会对数据库插入、查找、更新操作造成严重的性能影响?
如果字段数不多,对性能没有多大影响
1 数据有没有那么多
2 数据会不会在不同的Master上生成UUID也分好几类:/**
*
* A class that represents an immutable universally unique identifier (UUID).
* A UUID represents a 128-bit value.
*
* <p>There exist different variants of these global identifiers. The methods
* of this class are for manipulating the Leach-Salz variant, although the
* constructors allow the creation of any variant of UUID (described below).
*
* <p>The layout of a variant 2 (Leach-Salz) UUID is as follows:
*
* The most significant long consists of the following unsigned fields:
* <pre>
* 0xFFFFFFFF00000000 time_low
* 0x00000000FFFF0000 time_mid
* 0x000000000000F000 version
* 0x0000000000000FFF time_hi
* </pre>
* The least significant long consists of the following unsigned fields:
* <pre>
* 0xC000000000000000 variant
* 0x3FFF000000000000 clock_seq
* 0x0000FFFFFFFFFFFF node
* </pre>
*
* <p>The variant field contains a value which identifies the layout of
* the <tt>UUID</tt>. The bit layout described above is valid only for
* a <tt>UUID</tt> with a variant value of 2, which indicates the
* Leach-Salz variant.
*
* <p>The version field holds a value that describes the type of this
* <tt>UUID</tt>. There are four different basic types of UUIDs: time-based,
* DCE security, name-based, and randomly generated UUIDs. These types
* have a version value of 1, 2, 3 and 4, respectively.
*
* <p>For more information including algorithms used to create <tt>UUID</tt>s,
* see <a href="http://www.ietf.org/rfc/rfc4122.txt">
* <i>RFC 4122: A Universally Unique IDentifier (UUID) URN
* Namespace</i></a>, section 4.2 "Algorithms for Creating a Time-Based
* UUID".
*
* @version 1.18, 06/02/06
* @since 1.5
*/
摘自jdk的UUID注释其中第4类,也就是完全随机生成的UUID,比如:
33d2cb38-303a-4886-b4b2-09016ad548f1
eb6f71cc-9aff-4f29-a674-56c7a8bf5938
0e6c77c9-425b-4678-baee-36808ad89e96在主键/索引里面的顺序是
0e6c77c9-425b-4678-baee-36808ad89e96
33d2cb38-303a-4886-b4b2-09016ad548f1
eb6f71cc-9aff-4f29-a674-56c7a8bf5938与其物理存储的位置不相符,导致索引之后需要扫描相应行的其他字段的时候,需要往复运动,影响效率。而基于时钟的或者其他相对“顺序”的UUID,就不会有这个问题。因此选用的时候必须考虑清楚。
aa75904a-5cab-11df-bbb5-000c29e30cf0
b1efddae-5cab-11df-bbb5-000c29e30cf0
bff83279-5cab-11df-bbb5-000c29e30cf0
c1d87ba7-5cab-11df-bbb5-000c29e30cf0
0828093c-5cac-11df-bbb5-000c29e30cf0
30a06204-5cad-11df-bbb5-000c29e30cf0是不是用的时候把顺序倒过来,就可以大大提高性能?比如最后一个改成:
000c29e30cf0-bbb5-11df-5cad-30a06204
如果这样,应该来说影响不大,你的主键相当于
uuid char(36) primary key
不会,反而不如正着!正着的时候,通过第一个字符,就可以减少很多记录。而反过来,你要到第十几个字符才发现不同。不利于Btree索引。
按你的说法,反而是随机生成的UUID效率高,这有点违反直觉
很明显你觉得让你在上述两个数据中找出某个值,你觉得哪个快?
我16777216条测试记录,没有看出明显差异(包括添加其他各种字段,包括text),唯一的区别是,空间上似乎改变顺序后大了很多(无论是数据的,还是在其他字段上加的索引占据的空间)。选择优化表后,空间一致。求解释。我理论上认为开头不一致的btree会层次更少,应该更快。
unhex(replace('a3eea910-5cab-11df-bbb5-000c29e30cf0','-','');
检索出来的时候用hex()这样主键只有原来的一半,效率要高些