我有一对多关系的两个表。假设对于表格中的每一行,表格foo中可以有0或更多行bar引用foo。
foo
bar
客户想要知道bar引用某行中有多少行foo,对于中的所有行foo。
我可以使用以下查询完成此操作:
SELECT count(bar_id) FROM bar WHERE bar.foo_id = foo.foo_id;
但是,如果表foo和bar很大,该怎么办?假设foo有100万行,并且bar有1000万行。我们还要说,其中99%的行的引用foo计数少于1000bar行。假设客户通常一次请求大约100行foo。
我应该将朴素的count()查询与外键上的索引一起使用,还是最好保留一个计数器?甚至有可能保持反击吗?bar我相信通过使用触发器上的原子增量和减量来更新计数器,我相信这是可能的,但我可能是错的。
也许违反直觉,您可能会发现简单的count方法会更快,除非您的工作量非常倾向于读取。
count
原因是计数器表的作用是序列化更新,因此foo在任何给定时间只能进行更新给定给定的一个事务。这是因为用于更新计数器的触发器的更新将锁定foo计数器表中的该条目,并且在事务回滚或提交之前不会释放该条目。
更糟糕的是,如果您的事务影响多个事务,foo而另一事务也受到影响,则您很有可能由于死锁而使其中一个事务中止。
坚持简单的计数,直到您有充分的理由进行更改为止。