我有一张表格,其中包含有关“交易”的数据。交易要么关闭要么已经打开,并且在'is_closed'列中标记为交易。 (或者当然,索引)。
大约有10,000个“开放”行和10,000,000个“已关闭”行。每个“打开”行每秒更新一次。 (此处仅更新索引字段)。一旦“关闭”一行,它将永远不会再次更新。 (只读)。
我永远不需要运行一个处理打开和关闭行的选择,所以问题是; 我应该将表格分成两个表格(打开和关闭),具有相同的结构吗?
单个表的缺点是每秒我在10,000,000行表上运行更新。 两个表的缺点是存在一种代码重复,并且在关闭“交易”时我需要将它们从一个表中删除,然后添加到另一个表中。
答案 0 :(得分:1)
我认为您可以按状态列partition进行表格,因此您将在逻辑上拥有1个表格。 List partition似乎适用于您的情况。然后,如果需要,您可以进一步分区“关闭”分区...
答案 1 :(得分:1)
如果关闭与开放的比率>> 1000(如您所述)那么最好制作两个不同的表格。
您可以通过使用多态来避免代码重复。您可以按名称 AbstractDeal 创建一个抽象基类交易,然后扩展两个具体类 OpenDeal 和 CloseDeal 。您可以分别使用表格映射这两个具体类。
我希望这是一个更好的解决方案。
答案 2 :(得分:1)
在某些情况下,像你这样的布尔(true和false,或1和0)列很好,但是如果你发现自己索引了这样一个列,你可能已经超越了这一行。
如果值均匀分布(50%为真,50%为假),MySQL甚至不会使用索引,除非它是覆盖索引。通过返回大部分数据集的二级索引寻找每一行的成本很高,因此MySQL将进行简单的表扫描。
在您的情况下,由于您要查询较小的发行版(1%false),MySQL实际上可能会使用索引。
然而,你不得不想知道为什么你必须在索引中存储那些甚至没有被使用的真值,但是,它们会减慢索引更新速度,而且只是浪费空间。
<强> ... REVISED ... 强>
相反,请考虑以另一个表的形式将索引存储在外部。考虑添加一个名为open_deals的表,其中包含以下结构,其中deal_id是交易和open_deals的主键:
deal_id
----------
100
121
135
要获得未结交易,只需执行以下操作:
SELECT deals.*
FROM open_deals
STRAIGHT_JOIN deals
ON deals.deal_id = open_deals.deal_id
我们使用直接连接,因为我们总是知道我们将从左到右加入,并且我们正在考虑将MySQL保存起来。
由于open_deals只包含一个索引列,因此索引将充当覆盖索引。在配置正确,功能强大的服务器上,索引将存储在内存中,因此表格将非常快。
内部的连接类似于使用原始的二级索引,但没有所有这些未使用的值的开销。
为了获得最佳性能,请确保将新值附加到open_deals表的末尾,或者换句话说,所有新值都应该大于最后一个,但无论如何你都要这样做。
要设置要打开的交易,请将其附加到open_deals表,并将其标记为已关闭,请从open_deals表中删除该ID。
这里的优点是你不必在表之间移动记录,不得不更新其他索引(甚至更糟的是使用InnoDB的聚簇索引)。这里唯一更新的索引是open_deals表上相当小的索引。
答案 3 :(得分:1)
将它们分成两个表格。我认为没有缺点:
那又怎样?你的目标是性能,而不是更少的代码。
更多代码行。一些UPDATE过程将转换为INSERT / DELETE过程。
优点是:
open/closed
标志)都会稍微窄一些。 答案 4 :(得分:0)
只要两个表都在同一个表空间中,您就可以从分割或分割表中获得任何好处 - 代码简单性的好处非常有利于将它保存在一个表中。
InnoDB将执行行级锁定,因此您不会最终阻止打开的阻止交易。