zoukankan      html  css  js  c++  java
  • 请给你的Mysql(InnoDB)表加上主键吧

    为什么一定要加主键?

    对于Mysql数据库,现在一般用的都是InnoDB存储引擎,InnoDB的索引结构是B+Tree,B+Tree可以分为聚集索引和非聚集索引,在InnoDB里为聚集索引
    在InnoDB中,表数据文件本身就是按B+Tree组织的一个索引结构,这棵树的叶节点data域保存了完整的数据记录。主键索引的key是数据表的主键,因此InnoDB表数据文件本身就是主索引
    因为InnoDB的数据文件本身要按主键聚集,所以InnoDB要求表必须有主键(MyISAM可以没有)

    没主键怎么办?

    我们在建表时发现是可以不指定主键的,那没指定主键的表,Mysql是怎么处理的呢?
    Mysql的官方文档是这么写的:

    • When you define a PRIMARY KEY on your table, InnoDB uses it as the clustered index. Define a primary key for each table that you create. If there is no logical unique and non-null column or set of columns, add a new auto-increment column, whose values are filled in automatically.
    • If you do not define a PRIMARY KEY for your table, MySQL locates the first UNIQUE index where all the key columns are NOT NULL and InnoDB uses it as the clustered index.
    • If the table has no PRIMARY KEY or suitable UNIQUE index, InnoDB internally generates a hidden clustered index named GEN_CLUST_INDEX on a synthetic column containing row ID values. The rows are ordered by the ID that InnoDB assigns to the rows in such a table. The row ID is a 6-byte field that increases monotonically as new rows are inserted. Thus, the rows ordered by the row ID are physically in insertion order.
    • 如果定义了主键,那么InnoDB会使用主键作为聚集索引。为您创建的每个表定义一个主键。 如果没有逻辑唯一且非空的列或列集,请添加一个新的自动递增列,其值将自动填充。
    • 如果没有定义主键,那么会使用第一非空的唯一索引(NOT NULL and UNIQUE INDEX)作为聚集索引
    • 如果既没有主键也找不到合适的非空索引,那么InnoDB会自动生成一个不可见的名为ROW_ID的列名为GEN_CLUST_INDEX的聚簇索引,该列是一个6字节的自增数值,随着插入而自增

    如果没定义主键,Mysql也会给你加上主键,而加的主键ROW_ID,其自增的实现来源于一个全局的序列,而所以有ROW_ID的表共享该序列,这也意味着插入的时候生成需要共享一个序列,那么高并发插入的时候为了保持唯一性就避免不了锁的竞争,进而影响性能
    所以还是自己乖乖的加上主键吧

    选什么字段作为主键呢?

    表数据存储在B+Tree的叶子节点上,且按主键的顺序存放。因此每插入一条记录时,会根据其主键将其插入节点的适当位置。如果节点达到装载因子(InnoDB默认为15/16),则开辟一个新节点。
    所以如果主键是自增的,则每次插入新的数据就会顺序添加到叶子节点上。这样就不需要移动叶子节点上的数据。效率更高,所占存储空间也更紧凑。

    所以建议用自增字段作为主键

    自增字段作为主键有没有缺点呢?
    《高性能Mysql》:

    对于高并发工作负载,在InnoDB中按主键顺序插入可能会造成明显的争用。主键的上届会变成“热点”。因为所有的插入都发生在这里,所以并发插入可能导致间隙锁竞争。另一个热点可能是AUTO_INCREMENT锁机制;如果遇到这个问题,则可能需要考虑重新设计表或者应用,或者更改innodb_autoinc_lock_mode配置。如果你的服务器版本还不支持innodb_autoinc_lock_mode参数,可以升级到新版本的InnoDB,可能对这种场景会工作得更好。

    总结

    对于InnoDB存储引擎,表一定要自己设定主键(你不设,mysql也会帮你设,而且还有隐患)
    建议用自增的字段作为主键

  • 相关阅读:
    代码编辑
    作业7
    实验 13 综合练习三
    模版 实验二 概要设计
    在线评测系统(OJ)使用方法
    作业 6 结构体
    结构体简介
    实验 10 指针2
    (第一周)软件工程四人组
    (第一周)读《构建之法》
  • 原文地址:https://www.cnblogs.com/liuwhut/p/12840137.html
Copyright © 2011-2022 走看看