精华内容
下载资源
问答
  • 实测 Mysql UUID 性能网上普遍认为Mysql 使用 UUID 主键性能低下,甚至建议用 自增ID 作为主键并用 UUID作唯一索引的方案。但没有提供具体的数据证明使用 UUID 作为主键时性能究竟低下到何种程度。为此我专门做了...

    实测 Mysql UUID 性能

    网上普遍认为Mysql  使用 UUID 主键性能低下,甚至建议用 自增ID 作为主键并用 UUID作唯一索引的方案。但没有提供具体的数据证明使用 UUID 作为主键时性能究竟低下到何种程度。为此我专门做了测试。

    测试环境:WindowsXP ,内存 4G , CPU : Duo T6570 , mysql : 5.1.36

    测试准备:

    1、 建表

    我建了3 个表来做性能比对

    表一:uuidtest_inno

    CREATE TABLE `uuidtest_inno` (

    `id` char(36) CHARACTER SET utf8 NOT NULL DEFAULT '',

    PRIMARY KEY (`id`)

    ) ENGINE=InnoDB DEFAULT CHARSET=latin1

    表二:uuidtest_myisam

    CREATE TABLE `uuidtest_myisam` (

    `id` char(36) CHARACTER SET utf8 NOT NULL DEFAULT '',

    PRIMARY KEY (`id`)

    ) ENGINE=MyISAM DEFAULT CHARSET=latin1

    表三:uuidtest_int

    CREATE TABLE `uuidtest_int` (

    `id` int(11) NOT NULL AUTO_INCREMENT,

    `test` varchar(255) CHARACTER SET latin1 DEFAULT NULL,

    PRIMARY KEY (`id`)

    ) ENGINE=MyISAM DEFAULT CHARSET=utf8

    可以看到,表一使用UUID 主键,引擎为 InnodB ;表二使用 UUID 主键,引擎为 MyISAM ;表三使用 自增ID ,引擎为MyISAM ;

    1、 编写存储过程

    编写存储过程分别插入100000 条记录:

    p_uuid_inno

    BEGIN

    set @i = 0;

    while @i < 100000 do

    insert into uuidtest_inno value(uuid());

    set @i = @i+1;

    end while ;

    END

    p_uuid_myisam

    BEGIN

    set @i = 0;

    while @i < 100000 do

    insert into uuidtest_myisam value(uuid());

    set @i = @i+1;

    end while ;

    END

    p_uuid_int

    BEGIN

    set @i = 0;

    while @i < 100000 do

    insert into uuidtest_int(test) value("test");

    set @i = @i+1;

    end while ;

    END

    1、 运行

    [SQL] call p_uuid_int;

    影响的数据栏: 0

    时间: 12.922ms

    call p_uuid_myisam;

    影响的数据栏: 0

    时间: 15.078ms

    call p_uuid_inno;

    影响的数据栏: 0

    时间: 4460.297ms

    结论:当数据表的引擎为MyISAM 时,自增 ID 无疑是效率最高的, UUID 效率略低,但不会低到无法接受。一旦数据引擎为 InnodB 时,效率下降非常严重,已经达到令人发指的地步。由于 InnodB 主键采用 聚集索引 ,会对插入的记录进行物理排序,而 UUID本身基本上是无序的,所以造成了巨大的 I/O 开销。所以如果使用 innodB  千万不要使用 UUID 。

    转载:http://cornerxp.iteye.com/blog/977463

    展开全文
  • 索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率,但这样也会降低索引的选择性。索引的选择性是指不重复的索引值(也称为基数,cardinality)和数据表的记录总数的比值。计算公式:SELECT COUNT...

    前缀索引,是指对于VARCHAR/TEXT/BLOB类型的字段建立索引时一般都会选择前N个字符作为索引。索引很长的字符列,会让索引变得大且慢。索引开始的部分字符,这样可以大大节约索引空间,从而提高索引效率,但这样也会降低索引的选择性。索引的选择性是指不重复的索引值(也称为基数,cardinality)和数据表的记录总数的比值。

    计算公式:

    SELECT COUNT(DISTINCT(a))/COUNT(*) FROM table1;

    SELECT COUNT(DISTINCT(LEFT((UUID),2)))/COUNT(1) AS ind2,

    COUNT(DISTINCT(LEFT((UUID),3)))/COUNT(1) AS ind3,

    COUNT(DISTINCT(LEFT((UUID),4)))/COUNT(1) AS ind4,

    COUNT(DISTINCT(LEFT((UUID),5)))/COUNT(1) AS ind5,

    COUNT(DISTINCT(LEFT((UUID),6)))/COUNT(1) AS ind6,

    COUNT(DISTINCT(LEFT((UUID),7)))/COUNT(1) AS ind7

    FROM table_a;

    选择=5的时候 即索引长度为5[效果更加接近1]

    如何给字段的后几个字符加索引而不是给整个字段加

    表里边有一个字段image_url,想给他加索引但是这个字段有很多内容是重复的如下:

    image_url

    http://img1.douban.com/lpic/s10419031.jpg

    http://img1.douban.com/lpic/s10419532.jpg

    http://img2.douban.com/lpic/s10412033.jpg

    http://img2.douban.com/lpic/s10412034.jpg

    给整个字段加索引会不会有问题啊?

    能不能就只给这个字段的后13个字符加索引啊,因为这13个字符才是我查找用的数据?

    还有加上以后用这个索引的时候,要注意哪些东西?

    据我所知,MYSQL没有后缀索引(如果说错请指正);

    如果真相要对这个字段添加索引又不想加整个字段,给你出歪招,程序可能稍微多一步。

    创建字段image_url 按你的字符数添加前缀索引。存取该字段时反转字符传存储。结果如下:

    gpj.13091401s/cipl/moc.nabuod.1gmi//:ptth

    查询的时候反转一下就可以了。

    SELECT COUNT(DISTINCT(LEFT(REVERSE(msg_id),2)))/COUNT(1) AS ind2,

    COUNT(DISTINCT(LEFT(REVERSE(msg_id),3)))/COUNT(1) AS ind3,

    COUNT(DISTINCT(LEFT(REVERSE(msg_id),4)))/COUNT(1) AS ind4,

    COUNT(DISTINCT(LEFT(REVERSE(msg_id),5)))/COUNT(1) AS ind5,

    COUNT(DISTINCT(LEFT(REVERSE(msg_id),6)))/COUNT(1) AS ind6,

    COUNT(DISTINCT(LEFT(REVERSE(msg_id),7)))/COUNT(1) AS ind7

    FROM table_a;

    选择=6的时候 即索引长度为6

    使用了反转函数 因为前面几位是相同的,所以在建表的时候将数据反写存进去,取得时候使用REVERSE反取一下即可

    展开全文
  • MySQL索引和存储引擎

    2020-09-25 22:25:28
    目录MySQL索引二叉树平衡二叉树红黑树Hash表BTreeB+TreeMySQL存储引擎MyISAM存储引擎数据存储形式锁的粒度事务数据的存储特点索引实现其他**InnoDB存储引擎***...而UUID索引效率比较低?为什么非主键索引结构叶子节点存

    MySQL索引

    索引是帮助MySQL高效获取数据的排好序数据结构

    索引数据结构,主要包含以下几类,我们来对比下

    • 二叉树
    • 平衡二叉树
    • 红黑树
    • Hash表
    • B-Tree

    二叉树

    **定义:**每个结点最多有两个子树,左子树比父节点小,右子树比父节点大。

    缺点:会出现极端情况导致整棵树只有左子树或只有右子树。

    平衡二叉树

    定义:平衡二叉树又称AVL树,是一种特殊的二叉查找树,其左右子数都是平衡二叉树,且左右子树高度差的绝对值不超过1。

    缺点:AVL树是高度平衡的,频繁的插入和删除,会引起频繁的rebalance,导致效率下降。

    红黑树

    定义

    • 性质1. 节点是红色或黑色。
    • 性质2. 根节点是黑色。
    • 性质3 每个红色节点的两个子节点都是黑色。(从每个叶子到根的所有路径上不能有两个连续的红色节点)
    • 性质4. 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

    缺点:数据量大会导致树层数比较多,这样就会造成查找数据慢。

    Hash表

    定义:散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。 对目标值进行hash运算得到hash值和数据磁盘指针地址保存到hash表,这样就达到快速定位数据位置。

    缺点:精确查找十分快速,但范围查找就碰壁了。

    BTree

    定义

    • 一个节点可以存储多个数据,这样可以避免黑红树的缺点,树的层数很变小;
    • 叶节点具有相同的深度,叶节点的指针为空;
    • 所有索引元素不重复;
    • 节点中的数据索引从左到右递增排列。

    缺点:节点里面数组数据:每个数据的结构=索引数据+数据记录(即叶子节点存储键值和数据记录)。

    MySQL索引是怎么支撑千万级表的快速查找?

    每个节点占用一个盘块的磁盘空间,一个节点上有两个升序排序的关键字和三个指向子树根节点的指针,指针存储的是子节点所在磁盘块的地址。两个关键词划分成的三个范围域对应三个指针指向的子树的数据的范围域。以根节点为例,关键字为17和35,P1指针指向的子树的数据范围为小于17,P2指针指向的子树的数据范围为17~35,P3指针指向的子树的数据范围为大于35。

    模拟查找关键字29的过程:

    1. 根据根节点找到磁盘块1,读入内存。【磁盘I/O操作第1次】

      比较关键字29在区间(17,35),找到磁盘块1的指针P2。

    2. 根据P2指针找到磁盘块3,读入内存。【磁盘I/O操作第2次】

      比较关键字29在区间(26,30),找到磁盘块3的指针P2。

    3. 根据P2指针找到磁盘块8,读入内存。【磁盘I/O操作第3次】

      在磁盘块8中的关键字列表中找到关键字29。

    分析上面过程,发现需要3次磁盘I/O操作,和3次内存查找操作。由于内存中的关键字是一个有序表结构,可以利用二分法查找提高效率。而3次磁盘I/O操作是影响整个B-Tree查找效率的决定因素。B-Tree相对于AVLTree缩减了节点个数,使每次磁盘I/O取到内存的数据都发挥了作用,从而提高了查询效率。

    B+Tree

    定义:B+Tree是在B-Tree基础上的一种优化。节点里面数组数据:每个数据只存储键信息,这样不存数据可以腾出空间放更多的键信息,让树层数越小

    • 非叶子节点不存储data,只存储索引(冗余),可以放更多的索引
    • 叶子节点包含所有索引字段
    • 叶子节点·用指针连接,提高区间访问的性能

    将上一节中的B-Tree优化,由于B+Tree的非叶子节点只存储键值信息,假设每个磁盘块能存储4个键值及指针信息,则变成B+Tree后其结构如下图所示:

    MySQL索引是怎么支撑千万级表的快速查找?

    通常在B+Tree上有两个头指针,一个指向根节点,另一个指向关键字最小的叶子节点,而且所有叶子节点(即数据节点)之间是一种链式环结构。因此可以对B+Tree进行两种查找运算:一种是对于主键的范围查找分页查找,另一种是从根节点开始,进行随机查找

    可能上面例子中只有22条数据记录,看不出B+Tree的优点,下面做一个推算:

    InnoDB存储引擎中页的大小为16KB,一般表的主键类型为 INT(占用4个字节)或 BIGINT(占用8个字节),指针类型也一般为4或8个字节,也就是说一个页(B+Tree中的一个节点)中大概存储16KB/(8B+8B)=1K个键值。(因为是估值,为方便计算,这里的K取值为〖10〗3)。**也就是说一个深度为3的B+Tree索引可以维护103 * 10^3 * 10^3 = 10亿 条记录**。

    实际情况中每个节点可能不能填充满,因此在数据库中,B+Tree的高度一般都在24层。MySQL的InnoDB存储引擎在设计时是将根节点常驻内存的,也就是说查找某一键值的行记录时最多只需要13次磁盘I/O操作。

    数据库中的B+Tree索引可以分为聚集索引(clustered index)和 辅助索引(secondary index)。上面的B+Tree示例图在数据库中的实现即为聚集索引,聚集索引的B+Tree中的叶子节点存放的是整张表的行记录数据。

    辅助索引与聚集索引的区别在于辅助索引的叶子节点并不包含行记录的全部数据,而是存储相应行数据的聚集索引键,即主键。当通过辅助索引来查询数据时,InnoDB存储引擎会遍历辅助索引找到主键,然后再通过主键在聚集索引中找到完整的行记录数据。

    MySQL存储引擎

    数据库存储引擎是数据库底层软件组件,数据库管理系统使用数据引擎进行创建、查询、更新和删除数据操作。不同的存储引擎提供不同的存储机制、索引技巧、锁定水平等功能,使用不同的存储引擎还可以获得特定的功能。

    现在许多数据库管理系统都支持多种不同的存储引擎。MySQL 的核心就是存储引擎。

    • InnoDB 事务型数据库的首选引擎,支持事务安全表(ACID),支持行锁定和外键。MySQL 5.5.5 之后,InnoDB 作为默认存储引擎。
    • MyISAM 是基于 ISAM 的存储引擎,并对其进行扩展,是在 Web、数据仓储和其他应用环境下最常使用的存储引擎之一。MyISAM 拥有较高的插入、查询速度,但不支持事务。
    • MEMORY 存储引擎将表中的数据存储到内存中,为查询和引用其他数据提供快速访问。

    MySQL 提供了多个不同的存储引擎,包括处理事务安全表的引擎和处理非事务安全表的引擎。在 MySQL 中,不需要在整个服务器中使用同一种存储引擎,针对具体的要求,可以对每一个表使用不同的存储引擎。

    可以利用 SHOW ENGINES 语句来显示可用的数据库引擎和默认引擎。

    可以根据以下的原则来选择 MySQL 存储引擎:

    • 如果要提供提交、回滚和恢复的事务安全(ACID 兼容)能力,并要求实现并发控制,InnoDB 是一个很好的选择。
    • 如果数据表主要用来插入和查询记录,则 MyISAM 引擎提供较高的处理效率。
    • 如果只是临时存放数据,数据量不大,并且不需要较高的数据安全性,可以选择将数据保存在内存的 MEMORY 引擎中,MySQL 中使用该引擎作为临时表,存放查询的中间结果。
    • 如果只有 INSERT 和 SELECT 操作,可以选择Archive 引擎,Archive 存储引擎支持高并发的插入操作,但是本身并不是事务安全的。Archive 存储引擎非常适合存储归档数据,如记录日志信息可以使用 Archive 引擎。

    使用下面的语句可以修改数据库临时的默认存储引擎 SET default_storage_engine=< 存储引擎名 > 注意:将 MySQL 数据库的临时默认存储引擎修改为 其他的存储引擎时 ,但是当再次重启客户端时,默认存储引擎仍然是 InnoDB。

    MyISAM存储引擎

    数据存储形式

    MyISAM采用的是索引与数据分离的形式,将数据保存在三个文件中.frm 、.MYD、.MYI。

    • .frm : 存储表结构
    • .MYD : 存储表数据
    • .MYI :存储表索引
    锁的粒度

    MyISAM不支持行锁,所以读取时对表加上共享锁,在写入是对表加上排他锁。由于是对整张表加锁,相比InnoDB,在并发写入时效率很低。

    事务

    MyISAM不支持事务

    数据的存储特点

    MyISAM是基于非聚簇索引进行存储的。

    索引实现

    MyISAM索引文件和数据文件是分离的(非聚集)

    其他

    MyISAM提供了大量的特性,包括全文索引,压缩,空间函数,延迟更新索引键等。

    • 进行压缩后的表是不能进行修改的,但是压缩表可以极大减少磁盘占用空间,因此也可以减少磁盘IO,从而提供查询性能。
    • 全文索引,是一种基于分词创建的索引,可以支持复杂的查询。
    • 延迟更新索引键,不会将更新的索引数据立即写入到磁盘,而是会写到内存中的缓冲区中,只有在清除缓冲区时候才会将对应的索引写入磁盘,这种方式大大提升了写入性能。

    InnoDB存储引擎

    数据存储形式

    使用InnoDB时,会将数据表分为.frm 和 .ibd 两个文件进行存储。

    • .frm : 存储表结构
    • .ibd : 存储表数据和索引

    innodb的所有数据文件(后缀为ibd的文件),他的大小始终都是16384(16k)的整数倍

    锁的粒度

    InnoDB采用**MVCC(多版本并发控制)**来支持高并发,InnoDB实现了四个隔离级别,默认级别是REPETABLE READ,并通过间隙锁策略防止幻读的出现。它的锁粒度是行锁。【MVCC在稍后会进行介绍】

    事务

    InnoDB是典型的事务型存储引擎,并且通过一些机制和工具,支持真正的热备份。

    数据的存储特点

    InnoDB表是基于聚簇索引建立的,聚簇索引对主键的查询有很高的性能,不过他的二级索引(非主键索引)必须包含主键列,索引其他的索引会很大。

    索引实现

    InnoDB索引实现(聚簇)

    • 表数据文件本身就是按B+Tree组织的一个索引结构文件
    • 聚簇索引-叶节点包含了完整的数据记录
    • 为什么InnoDB表必须有主键,并且推荐使用整型的自增主键?
    • 为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)

    联合索引

    底层数据结构:

    比较相等时,先比较第一列的值,如果相等,再继续比较第二列,以此类推。

    MySQL索引是怎么支撑千万级表的快速查找?

    最左前缀原理:

    使用联合索引时,索引列的定义顺序将会影响到最终查询时索引的使用情况。例如联合索引(a,b,c),mysql会从最左边的列优先匹配,如果最左边的带头大哥没有使用到,在未使用覆盖索引的情况下,就只能全表扫描。 联合底层数据结构思考,mysql会优先以联合索引第一列匹配,此后才会匹配下一列,如果不指定第一列匹配的值,也就无法得知下一步查询哪个节点。 另外还有一种情况,如果遇到 > < between等这样的范围查询,那B+树中也就无法对下一列进行等值匹配了。

    问题总结

    InnoDB一颗B+树可以存放多少行数据?

    这个问题的简单回答是:约2千万。为什么是这么多呢?因为这是可以算出来的。

    这里我们先假设B+树高为2,即存在一个根节点和若干个叶子节点,那么这棵B+树的存放总记录数为:根节点指针数单个叶子节点记录行数

    上文我们已经说明单个叶子节点(页)中的记录数=16K/1K=16。(这里假设一行记录的数据大小为1k,实际上现在很多互联网业务数据记录大小通常就是1K左右)。

    那么现在我们需要计算出非叶子节点能存放多少指针,其实这也很好算,我们假设主键ID为bigint类型,长度为8字节,而指针大小在InnoDB源码中设置为6字节,这样一共14字节,我们一个页中能存放多少这样的单元,其实就代表有多少指针,即16384/14=1170。那么可以算出一棵高度为2的B+树,能存放1170*16=18720条这样的数据记录。

    根据同样的原理我们可以算出一个高度为3的B+树可以存放:1170* 1170 *16=21902400条这样的记录。所以在InnoDB中B+树高度一般为1-3层,它就能满足千万级的数据存储。在查找数据时一次页的查找代表一次IO,所以通过主键索引查询通常只需要1-3次IO操作即可查找到数据。

    聚簇索引和非聚簇索引的区别
    • 聚簇索引:将数据存储与索引放到了一块,索引结构的叶子节点保存了行数据
    • 非聚簇索引:将数据与索引分开存储,索引结构的叶子节点指向了数据对应的位置
    为什么InnoDB表必须有主键,并且推荐使用整型的自增主键?
    1. 如果设置了主键,那么InnoDB会选择主键作为聚集索引,如果没有显式定义主键,则InnoDB会选择第一个不包含有NULL值的唯一索引作为主键索引、如果也没有这样的唯一索引,则InnoDB会选择内置6字节长的ROWID作为隐含的聚集索引(ROWID随着行记录的写入而主键递增)。
    2. 如果表使用自增主键

    那么每次插入新的记录,记录就会顺序添加到当前索引节点的后续位置,主键的顺序按照数据记录的插入顺序排列,自动有序。当一页写满,就会自动开辟一个新的页

    1. 如果使用非自增主键(如果身份证号或学号等)

    由于每次插入主键的值近似于随机,因此每次新纪录都要被插到现有索引页得中间某个位置,此时MySQL不得不为了将新记录插到合适位置而移动数据,甚至目标页面可能已经被回写到磁盘上而从缓存中清掉,此时又要从磁盘上读回来,这增加了很多开销,同时频繁的移动、分页操作造成了大量的碎片,得到了不够紧凑的索引结构,后续不得不通过OPTIMIZE TABLE来重建表并优化填充页面。

    MySQL为什么用自增作为索引比较好。而UUID索引效率比较低?

    聚簇索引的数据的物理存放顺序与索引顺序是一致的,即:只要索引是相邻的,那么对应的数据一定也是相邻地存放在磁盘上的。如果主键不是自增id,那么可以想象,它会干些什么,不断地调整数据的物理地址、分页,当然也有其他一些措施来减少这些操作,但却无法彻底避免。但,如果是自增的,那就简单了,它只需要一页一页地写,索引结构相对紧凑,磁盘碎片少,效率也高。

    • 索引存储在磁盘,而且树的每个节点分配的空间有大小。整型占空间比较小,这样可以存放多个键值。反之然后UUID占空间比较大。
    • 整型比较方便,UUID比较需要先转成ASCII在进行比较。
    为什么非主键索引结构叶子节点存储的是主键值?(一致性和节省存储空间)
    1. 减少了出现行移动或者数据页分裂时二级索引的维护工作(当数据需要更新的时候,二级索引不需要修改,只需要修改聚簇索引,一个表只能有一个聚簇索引,其他的都是二级索引,这样只需要修改聚簇索引就可以了,不需要重新构建二级索引);
    2. 聚簇索引也称为主键索引,其索引树的叶子节点中存的是整行数据,表中行的物理顺序与键值的逻辑(索引)顺序相同。一个表只能包含一个聚集索引。因为索引(目录)只能按照一种方法进行排序;
    3. 非聚簇索引(普通索引)的叶子节点内容是主键的值。在 InnoDB 里,非主键索引也被称为二级索引(secondary index)。
    展开全文
  • uuid介绍 在我以前的文章中,我讨论了UUID代理密钥以及...由于通常对表标识符进行索引,因此数据库类型越紧凑,索引所需的空间就越少。 从效率最高到最低,这是我们的选择: 某些数据库( PostgreSQL , SQL Ser...
    uuid

    uuid

    介绍

    我以前的文章中,我讨论了UUID代理密钥以及用例这些用例比更常见的自动增量标识符更合适。

    UUID数据库类型

    有几种表示128位UUID的方法,每当有疑问时,我都希望向Stack Exchange寻求专家意见。

    由于通常对表标识符进行索引,因此数据库类型越紧凑,索引所需的空间就越少。 从效率最高到最低,这是我们的选择:

    1. 某些数据库( PostgreSQLSQL Server )提供专用的UUID存储类型
    2. 否则,我们可以将这些位存储为字节数组(例如,Oracle中的RAW(16)或标准BINARY(16)类型)
    3. 另外,我们可以使用2个bigint(64位)列,但是复合标识符的效率要比单个列低
    4. 我们可以将十六进制值存储在CHAR(36)列中(例如32个十六进制值和4个破折号),但这将占用最多的空间,因此这是效率最低的替代方法

    Hibernate提供了许多标识符策略供您选择,对于UUID标识符,我们有三种选择:

    • 分配的生成器以及应用程序逻辑UUID生成
    • 十六进制“ uuid”字符串生成器
    • 更灵活的“ uuid2”生成器,允许我们使用java.lang.UUID ,16字节数组或十六进制String值

    分配的发电机

    分配的生成器允许应用程序逻辑控制实体标识符生成过程。 通过简单地省略标识符生成器定义,Hibernate将考虑分配的标识符。 此示例使用BINARY(16)列类型,因为目标数据库是HSQLDB

    @Entity(name = "assignedIdentifier")
    public static class AssignedIdentifier {
    
        @Id
        @Column(columnDefinition = "BINARY(16)")
        private UUID uuid;
    
        public AssignedIdentifier() {
        }
    
        public AssignedIdentifier(UUID uuid) {
            this.uuid = uuid;
        }
    }

    持久实体:

    session.persist(new AssignedIdentifier(UUID.randomUUID()));
    session.flush();

    恰好生成一个INSERT语句:

    Query:{[insert into assignedIdentifier (uuid) values (?)][[B@76b0f8c3]}

    让我们看看发出合并时会发生什么:

    session.merge(new AssignedIdentifier(UUID.randomUUID()));
    session.flush();

    这次我们同时获得了SELECT和INSERT:

    Query:{[select assignedid0_.uuid as uuid1_0_0_ from assignedIdentifier assignedid0_ where assignedid0_.uuid=?][[B@23e9436c]} 
    Query:{[insert into assignedIdentifier (uuid) values (?)][[B@2b37d486]}

    persist方法接受一个临时实体,并将其附加到当前的Hibernate会话中。 如果已经有一个附加的实体,或者如果当前的实体已分离,我们将得到一个异常。

    合并操作会将当前对象状态复制到现有的持久实体(如果有)中。 此操作适用于临时实体和分离实体,但是对于临时实体持久化要比合并操作有效得多。

    对于分配的标识符,合并将始终需要进行选择,因为Hibernate无法知道是否已经存在具有相同标识符的持久化实体。 对于其他标识符生成器,​​Hibernate会寻找一个空标识符以判断该实体是否处于过渡状态。

    这就是为什么Spring Data SimpleJpaRepository#save(S实体)方法不是使用分配的标识符的实体的最佳选择的原因:

    @Transactional
    public <S extends T> S save(S entity) {
        if (entityInformation.isNew(entity)) {
            em.persist(entity);
            return entity;
        } else {
            return em.merge(entity);
        }
    }

    对于分配的标识符,此方法将始终选择合并而不是持久化,因此您将为每个新插入的实体同时获得SELECT和INSERT。

    UUID生成器

    这次我们不会自己分配标识符,而是让Hibernate代表我们生成它。 当遇到一个空标识符时,Hibernate假定一个临时实体,为其生成一个新的标识符值。 这次,合并操作将不需要在插入过渡实体之前进行选择查询。

    UUIDHexGenerator

    UUID十六进制生成器是最古老的UUID标识符生成器,​​它以“ uuid”类型注册。 它可以生成具有以下模式的32位十六进制UUID字符串值(也可以使用分隔符):8 {sep} 8 {sep} 4 {sep} 8 {sep} 4。

    此生成器不符合IETF RFC 4122 ,它使用8-4-4-4-12数字表示。

    @Entity(name = "uuidIdentifier")
    public static class UUIDIdentifier {
    
        @GeneratedValue(generator = "uuid")
        @GenericGenerator(name = "uuid", strategy = "uuid")
        @Column(columnDefinition = "CHAR(32)")
        @Id
        private String uuidHex;
    }

    持久化或合并临时实体:

    session.persist(new UUIDIdentifier());
    session.flush();
    session.merge(new UUIDIdentifier());
    session.flush();

    每个操作生成一个INSERT语句:

    Query:{[insert into uuidIdentifier (uuidHex) values (?)][2c929c6646f02fda0146f02fdbfa0000]} 
    Query:{[insert into uuidIdentifier (uuidHex) values (?)][2c929c6646f02fda0146f02fdbfc0001]}

    您可以检出发送到SQL INSERT查询的字符串参数值。

    UUIDGenerator

    较新的UUID生成器符合IETF RFC 4122(版本2),并且提供可插拔生成策略。 它以“ uuid2”类型注册,并且提供了更大的类型范围供您选择:

    @Entity(name = "uuid2Identifier")
    public static class UUID2Identifier {
    
        @GeneratedValue(generator = "uuid2")
        @GenericGenerator(name = "uuid2", strategy = "uuid2")
        @Column(columnDefinition = "BINARY(16)")
        @Id
        private UUID uuid;
    }

    持久化或合并临时实体:

    session.persist(new UUID2Identifier());
    session.flush();
    session.merge(new UUID2Identifier());
    session.flush();

    每个操作生成一个INSERT语句:

    Query:{[insert into uuid2Identifier (uuid) values (?)][[B@68240bb]} 
    Query:{[insert into uuid2Identifier (uuid) values (?)][[B@577c3bfa]}

    当我们配置@Id列定义时,此SQL INSERT查询正在使用字节数组。

    翻译自: https://www.javacodegeeks.com/2014/07/hibernate-and-uuid-identifiers.html

    uuid

    展开全文
  • UUID几个缺点

    千次阅读 2018-03-21 10:47:45
    第一个 UUID字符串占用的空间比较大。 第二个 索引效率很低。 第三个 生成的ID很随机,不是人能读懂的。 第四个 做不了递增,如果要排序的话,基本不太可能。...
  • python的uuid都是32位的,比较长,处理起来效率比较低,本算法利用62个可打印字符,通过随机生成32位UUID,由于UUID都为十六进制,所以将UUID分成8组,每4个为一组,然后通过模62操作,结果作为索引取出字符,最后...
  • Hibernate和UUID标识符

    2020-06-15 16:45:52
    介绍 在我以前的文章中,我讨论了UUID代理密钥以及用例 , ... 由于通常对表标识符进行索引,因此数据库类型越紧凑,索引所需的空间就越少。 从效率最高到最低,这是我们的选择: 某些数据库( PostgreSQL , SQ...
  • 休眠和UUID标识符

    2020-05-19 05:25:39
    介绍 在我以前的文章中,我谈到了UUID代理密钥以及用例 , ... 由于通常对表标识符建立索引,因此数据库类型越紧凑,索引所需的空间就越少。 从效率最高到最低,这是我们的选择: 某些数据库( PostgreSQL ,...
  • Python生成短uuid的方法

    2018-05-29 09:37:00
    python的uuid都是32位的,比较长,处理起来效率比较低, 本算法利用62个可打印字符,通过随机生成32位UUID,由于UUID都为十六进制,所以将UUID分成8组,每4个为一组,然后通过模62操作,结果作为索引取出字符, ...
  • python的uuid都是32位的,比较长,处理起来效率比较低, 本算法利用62个可打印字符,通过随机生成32位UUID,由于UUID都为十六进制,所以将UUID分成8组,每4个为一组,然后通过模62操作,结果作为索引取出字符, 最后...
  • mysql主键自增和UUID的区别

    万次阅读 2020-06-29 23:35:21
    在进行数据库插入时,位置相对固定(B+树中的右下角)增加数据插入效率,减少插入的磁盘IO消耗,每页的空间在填满的情况下再去申请下一个空间,底层物理连续性更好,能更好的支持区间查找 2、UUID 由于UUID是随机...
  • Hibernate和UUID标示符

    2014-08-11 14:48:57
    由于表ID一般会建索引,经过压缩的数据类型会占用更少的空间。按照效率由高到低有如下几种选择: 一部分数据库(PostgreSQL, SQL Server) 提供了专门的UUID 存储数据类型。 另外还可把若干bit存放到字节数组...
  • 自增长id/UUID/雪花算法

    千次阅读 2020-05-09 19:22:28
    /雪花算法 自增长id/UUID 雪花算法的原理和实现 ...(3)ID自增:存入数据库中,索引效率高。 SnowFlake算法的缺点: 依赖与系统时间的一致性,如果系统时间被回调,或者改变,可能会造成id冲突或者重复。 ...
  • 主要原因是uuid在数据量较大的情况下,效率直线下滑。 使用uuid和自增id的索引结构对比 使用自增id的内部结构 ​ 自增的主键的值是顺序的,所以Innodb把每一条记录都存储在一条记录的后面。当达到页面的最大填充因子...
  • 缺点是字符串作为ID占用空间大,索引效率比整型低。如果采用整型作为ID,那么首先排除掉32位int类型,因为范围太小,必须使用64位long型。采用整型作为ID时,如何生成自增、全局唯一且不重复的ID?方案...
  • 索引并不是越多越好!索引可以提高查询效率,但会降低增删改效率。但多了甚至会降低查询效率。Innodb是按照主键索引的顺序来组织表,如...不使用联合索引作为主键,否则会降低性能2、不使用UUID,MD5,HASH,字符串作为...
  • 来源:cnblogs.com/wyq178/p/12548864.html前言一、mysql和程序实例1.1.要说明这个问题,我们首先来建立...效率测试结果二、使用uuid和自增id的索引结构对比2.1.使用自增id的内部结构2.2.使用uuid索引内部结构2.3....
  • innodb中不要用uuid作为主键

    千次阅读 2010-03-07 20:59:00
    因为innodb中索引和数据是存放在一起的(b-tree中存储key+row data),因此如果利用uuid作为主键的话,因为uuid是无序的,会造成插入时的排序和数据移动,带来很大的I/O,会影响效率。但是如果利用自增主键的话,...
  • mysql不要用uuid用自增主键,自增主键效率高innodb的索引特性导致了自增id做主键是效率最好的 测试: 1、准备表以及数据 UC_USER,自增ID为主键,表结构类似如下: CREATE TABLE `UC_USER` ( &...
  • 测试缘由 一个开发同事做了一个框架,里面主键是uuid,我跟他建议说MySQL不要用uuid用自增主键,自增主键效率高,他说不一定高,我说innodb的索引特性导致了自增id做主键是效率最好的,为了拿实际的案例来说服他,...
  • 【转载】一个开发同事做了一个框架,里面主键是uuid,我跟他建议说mysql不要用uuid用自增主键,自增主键效率高,他说不一定高,我说innodb的索引特性导致了自增id做主键是效率最好的,为了说服他,所以准备做一个...
  • 索引设计规范

    2019-05-05 01:26:47
    索引可以增加查询效率,但同样会降低插入和更新的效率)(所以要求每个innodb表必须有一个主键) 因为innodb是索引组织表的缘故,如果主键频繁被更新,意味着数据存储的逻辑数据要频繁变动,必然带来大量io操作和...
  • 02索引设计规范

    2020-09-25 21:00:41
    索引可以提高效率同样可以降低效率 禁止给表中的每一列都建立单独的索引 Innodb是按照哪个索引的顺序来组织表的呢? 答案是:主键 每个Innodb表必须有一个主键 不使用更新频繁的列作为主键,不使用多列主键 不使用...
  • 单实例数据库 ID用自增比用UUID更高效,涉及...索引效率低,2.安全容易泄露MAC地址。 综上上述原因,Twitter设计了Snowflake(雪花)算法,单调递增且不泄露MAC地址,美团的LEAF组件。 转载于:https://ww...
  • 这样可以使索引的维护更加方便,节约索引所占空间和提高索引效率。 2.当有多个索引的时候,把选择性高的放在前面,选择性低的放在后面,这样做可以提高索引效率。 3.聚簇索引要按主键顺序插入,而不是使用UUID随机...
  • mysql索引碎片

    2019-12-07 17:28:24
    选用的键随机性太大,不是有序增长的,比如uuid 删操作 碎片对性能的影响 内部碎片会增加IO操作。当执行的查询扫描部分或全部的表/索引时,如果那个表/索引上面有内部碎片,它会增加额外的页读取。在我们的例子里,...
  • (1)顺序主键和随机主键的对效率的影响很大。我们分插入和查询来讲: 插入。在磁盘中,有一个页的概念,而一页的容量是固定的,每一页按顺序存储数据,一般数据量达到一页的15/16,则开始存到下...
  • 数据索引自增

    2018-10-02 19:10:15
    b-tree 数据结构索引: 从这个数据接口上,细细咀嚼了一下索引自增。...自增,趋势自增,可作为聚集索引,提升查询效率2.节省磁盘空间。500W数据,UUID占5.4G,自增ID占2.5G.3.查询,写入效率高:查询略优。写...
  • 一个开发同事做了一个框架,里面主键是uuid,我跟他建议说mysql不要用uuid用自增主键,自增主键效率高,他说不一定高,我说innodb的索引特性导致了自增id做主键是效率最好的,为了说服他,所以准备做一个详细的测试...

空空如也

空空如也

1 2 3 4 5 ... 7
收藏数 122
精华内容 48
关键字:

uuid索引效率