这是示例表:
id | object_class | object_id | name |
1 | 1 | 1 | potato |
2 | 1 | 2 | tomato |
3 | 2 | 1 | wheel |
4 | 2 | 2 | seat |
id 自动递增。例如,我想在 object_class 等于 1 时添加行。如何告诉 mysql 在创建新行时,检查对象类中的 object_id,找到最大的一个并使用 object_id+1 创建行?如果 object_class 不存在,则创建 object_id 从 1 开始的新行?所以它补充道:
5 | 1 | 3 | foo | (for existing)
6 | 3 | 1 | bar | (for new object_class)
我确实明白我可以以某种方式(如果上述不可能,请解释用很少的查询来执行此操作的最佳优化方法)获取某些 object_class 的 object_id,然后找到最大的一个。之后,使用手动计算的 object_id 创建新行。但这似乎还有很多工作要做。
我想指出,我对 mysql 表优化了解不多。
另外,我使用 laravel 5 框架。
编辑:
刚刚注意到 laravel 有 Aggregate MAX http://laravel.com/docs/5.0/queries
获取最大值然后使用 max+1 创建新行是个好方法吗?
最佳答案
有四种方法可以实现此目的。
- 在您的 php 代码中执行所有操作。添加行,查询数据库以获取最大值。创造新记录。所有这些都是在 php 中完成的,并将 autocommit 设置为 false。如果出现问题,您希望能够回滚。要么一切按计划进行,两行按应有的方式插入,要么什么都不插入。
- 这与上面的相同。所有 php,但不是在数据库中搜索最大值,而是保留缓存。步骤是这样的:插入行,在缓存中搜索需要的内容,插入第二行,更新缓存。这样会更快,但是很麻烦,因为你必须考虑内存问题。是一些简单的数据结构,还是一些提供这种功能的框架?这些从一开始就很难决定。
- 创建一个
ON INSERT
运行的过程。当您插入行时,该触发器将被激活,并且它将运行您的 SQL 代码。该过程将检查最大值,然后插入新行。 - 与 2 相同,但是 run 你可以通过 php 运行你的程序,而不是通过触发器。
我完全支持情况 1 和 2。我倾向于尽可能避免过程和触发器。我不希望我的业务逻辑到处都是。我尝试将所有内容保留在代码中,因为它更易于维护且更易于调试。日志记录也更容易。代码库的新手可以轻松地遵循这些步骤。当然这是我的做法,不一定是正确的方法。在某些情况下,通过代码甚至通过触发器调用的过程可能非常有效,但在您的情况下我没有看到这一点。
在 1 和 2 之间做出选择,这很棘手。这取决于您的应用程序以及您想要实现的目标。 1 很简单,如果速度很慢,您可以尝试通过索引进行优化。如果这有效,那就这样做吧。就简单多了。如果没有,那么您必须考虑情况 2。为您需要的值保留缓存,而不是查询数据库。在启动时,您初始化缓存(这在启动时完成一次,所以即使有点慢,也只是一次)。然后保持缓存最新。如果简单和定制的东西可以,那就很好。如果没有,那么您就开始寻找一些处理此类内容的框架。
这是我的两分钱。我希望这可以帮到你。玩得开心
@zerkms 提供了一些非常有用的见解。你总是会遇到并发问题。所以基本上我知道解决这个问题的两种方法。
- 进行事务(所有三个步骤)时完全锁定表(悲观锁定)。当一笔交易发生时,其他交易不能做同样的事情,否则它会搞乱你所追求的最大值的查询。不建议这样做,特别是当应用程序打算提供一些流量时。
- 将所需的值保留在同步结构中。检查案例 2。建议这样做。这样,瓶颈只会发生在快速查找时,而不会发生在完整的数据库事务中。
关于php - 如何在mysql中根据条件增加行object_id?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29018607/