主键之间的差距会减慢查询速度吗?

时间:2019-03-22 15:31:22

标签: mysql sql

我有一个MySQL表,其中id是主键并自动递增。

由于我有一个使用ON DUPLICATE KEY每分钟运行一次cron作业(通过外部API更新统计信息),因此我在id列中发现了很多空白。我设置了一个唯一的列,这显然是造成差距的原因。

例如,只有183行,但是我已经在id列上了71511。

我运行的唯一SELECT查询与此类似:

SELECT * FROM table WHERE member = '123' ORDER BY id DESC LIMIT 30

我不在乎这个数字正在迅速增加,并且没有在其他任何地方使用。我只是想找出它是否会导致查询随时间推移变慢。

例如,如果我有一个具有100,000行的表,但是id处于十亿行,那么间隙会导致插入或选择的运行速度变慢吗?

2 个答案:

答案 0 :(得分:2)

不,存在差距因为,通过这种方式计算唯一标识符可以更快,更轻松地处理并发系统。

auto_increment的值是1还是755131与性能无关。

存储要求由您的表定义,自动增量的最常用存储标识符是4字节int。无论您存储什么数字,它都会占用4个字节(如果可以容纳4个字节的话)。

存在差距的原因是存在的,为什么它们不是问题。 Primary key是唯一标识符。计算唯一标识符的最简单方法是每次对表进行更改(插入,删除)时都增加一个数字。

此数字不是必需的顺序,而是唯一的。 MySQL使用顺序算法来计算唯一数字。

由于MySQL考虑到并发操作,因此每个事务都是隔离的(如果使用事务引擎)。如果事务引起对auto_increment的更改但未能记下,则auto_increment将永远花费。每个表只有一个计数器,没有代码检查该数字是否应该减少(这是浪费资源)-无论查询是否成功,它都只会增加。

这种方法保证:

  1. 性能-无需担心计数器的状态应该是什么(是否应该下降)

  2. 唯一性-这是计算行的唯一标识符的最快,最安全的方法-只需将数字增加auto_increment_offset。无需担心碰撞,什么也不担心。您可以100%确信,如果将最后一个数字加auto_increment_offset,则会在数据库中获得一个新的,唯一的且未使用的数字/

对于数据库,尤其是MySQL,在读写性能方面有多种因素。最小最大化和尝试摆弄auto_increment并不是其中之一。如果一切都保持不变,您会没事的。

如果您认为将超过4字节无符号整数的最大值(大约42亿美元),则可以考虑将主键更改为bigint。如果您每秒要插入数千条记录,那么您将不会超过数千年。

答案 1 :(得分:1)

通常,我会说这不是问题。但是,这引起了我的注意:

  

例如,只有183行,但我的id列已经在71511。

这是很多的空白。造成差距的通常原因是删除和插入失败(在其他数据库中,为了提高效率分配id块)。

您似乎了解这些差距。您可以在插入时稍稍用手即可消除它们:

insert into t ( . . . )
    select . . .  --values here
    from dual
    where not exists (select 1 from t t2 where . . .)  -- duplicate key catch here
    on duplicate key . . .;

仅在出现竞争情况时才需要重复密钥-where将在insert之前 消除大多数或全部密钥。这可能会消除所有差距。

对于具有100,000行的表必须使用bigint远非优雅。大整数将索引的大小加倍。它们增加了每个页面上的记录所需的存储量。增加数据库的大小会增加I / O开销。