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