【发布时间】:2013-12-11 12:29:48
【问题描述】:
我有一个表,其中包含一个标准的自动递增 ID、一个类型标识符、一个数字和一些其他不相关的字段。当我在这个表中插入一个新对象时,数字应该根据类型标识符自动增加。
以下是输出应如何显示的示例:
id type_id number
1 1 1
2 1 2
3 2 1
4 1 3
5 3 1
6 3 2
7 1 4
8 2 2
如您所见,每次插入新对象时,数字都会根据 type_id 递增(即,如果我插入 type_id 为 1 的对象并且已经有 5 个对象匹配此 type_id,则新对象上的数字应该是 6)。
我正在尝试找到一种高性能的方式来实现大量并发。例如,同一秒内可能有 300 次插入相同的 type_id,它们需要按顺序处理。
我已经尝试过的方法:
PHP
这是一个坏主意,但为了完整起见,我添加了它。已请求获取项目类型的 MAX() 编号,然后将编号 + 1 作为插入的一部分添加。这很快但不能同时工作,因为在对 MAX() 的请求和导致具有相同编号和 type_id 的多个对象的特定插入之间可能有 200 次插入。
锁定
在每次插入之前和之后手动锁定和解锁表,以保持增量。由于并发插入的数量以及在整个应用程序中不断读取表,这会导致性能问题。
子查询交易
这就是我目前的做法,但它仍然会导致大量性能问题:
START TRANSACTION;
INSERT INTO objects (type_id,number) VALUES ($type_id, (SELECT COALESCE(MAX(number),0)+1 FROM objects WHERE type_id = $type_id FOR UPDATE));
COMMIT;
这种方法的另一个负面影响是我需要进行后续查询才能获得添加的数字(即搜索具有按数字 desc 排序的 $type_id 的对象,以便我可以看到之前的数字创建 - 这是基于 $user_id 完成的,因此它可以工作,但添加了一个我想避免的额外查询)
触发器
我研究过使用触发器以便在插入时动态添加数字,但这并不高效,因为我需要对要插入的表执行查询(这是不允许的,因此必须在导致性能问题的子查询)。
分组自动增量
我查看了分组自动增量(以便数字会根据 type_id 自动增量),但后来我丢失了我的自动增量 ID。
是否有人对我如何在我需要的并发插入级别上实现此性能有任何想法?我的表目前是 MySQL 5.5 上的 InnoDB
感谢任何帮助!
更新:以防万一,对象表中有几百万个对象。一些type_id 可以分配大约500,000 个对象。
【问题讨论】:
-
我的想法是 - 使用组自动增量。那就是 - 关于 - 如果您的
<type_id, number>是唯一的(并且它必须是 - 由于您的逻辑) - 它可以是主键,那么代理id键的意义是什么?您甚至在寻找一种方法来使用您的组合来确定正确的行地址,因此id是多余的。如果它的目的是保持连续编号 - 为什么不在应用程序中应用它?所以看起来你的问题是关于如何在表中维护两个主键? - 这是设计上的错误 -
这听起来很有趣。我对这个更改的问题是应用程序已经在运行,并且有几百万个带有我要加入的 ID 的对象。作为一个基本示例,每个对象都可以附加许多“评论”,这些“评论”是通过在评论表上添加
object_id来完成的。如果我删除现有的主键并使用<type_id,number>,我将如何将这两个链接在一起?我以前从未使用过标准id模式以外的任何东西,主要是自动递增的。 -
嗯,这可能是一个想法,但你有
InnoDB。它不支持多列 auto_increment。所以这不是一个选择,对不起 -
从技术上讲,我可以将
id列从 int 更改为 varchar,然后在插入时生成 UUID。这将允许我保留代理键,以便我以前的所有联接等都可以工作,但这意味着我不会有两个自动增量?你认为这有意义吗? -
您不能使用 auto_increment 自动生成
number值,因为该机制仅适用于BDB和MyISAMstorage-engines
标签: php mysql auto-increment