microservices体系结构和mysql数据库分页

aoyhnmkz  于 2021-06-20  发布在  Mysql
关注(0)|答案(2)|浏览(332)

想象一下,我想检索一组客户的所有订单。这个 arrayList 在下面的示例中,将有一个客户id数组。
此数组将被传递到 get 方法,并异步检索数组中每个客户id的订单。
这就是我迷路的地方。如何对数据库结果集进行分页,一次只从数据库中提取一小部分记录,而不必通过网络提取所有记录。
让我困惑的是异步的本质以及我们不知道每个客户有多少订单?那么,如何高效地一次返回一个设置的页面大小呢?
服务.js

function callToAnotherService(id) {
    return new Promise((resolve, reject) => {
        //calls service passing id
    }
}

exports.get = arrayList => Promise.all(arrayList.map(callToAnotherService))
    .then((result) => result);
ckx4rj1h

ckx4rj1h1#

在mysql中,使用 ORDER BY ... LIMIT 30, 10 跳过30行,抓住10行。
最好记住你在哪里停下来了(比如说$left\u off),然后再做

WHERE id > $left_off
ORDER BY id
LIMIT 10

你抓到的最后一排是新的“left\u off”。
更好的是,但是 LIMIT 11 . 然后您可以显示10,但也可以发现是否还有更多(通过从 SELECT .

kuarbcqp

kuarbcqp2#

在mysql中,实现这一点的方法不止一种。
您选择的方法取决于许多变量,例如实际的分页方法(您是只希望有“上一页”和“下一页”按钮,还是希望提供1…n的范围,其中n是匹配记录的总数除以每页记录计数);另外还有数据库设计、计划增长、分区和/或分片、当前和预测的数据库负载、可能的硬查询限制(例如,如果您有多年的记录,您可能会要求最终用户为查询选择合理的时间范围(上个月、上3个月、上一年等等……),因此,它们不会用不受限制的、过于宽泛的查询等使数据库过载。。
分页:
使用简单的“上一步”和“下一步”按钮,您可以使用简单的限制[start\u at\u record,]number\u of \u records方法,正如rick james在上面提出的那样。
使用(所有)页码,您需要知道匹配记录的数量,因此根据页面大小,您可以知道总共有多少页。
混合使用上述两种方法。例如,您可以显示一些可单击的页码(例如上一页/下一页5),以及第一个和最后一个链接/按钮。
如果您从最后两个选项中选择一个,您肯定需要知道找到的记录的总数。
正如我上面所说,实现同一目标的方法不止一种。必须根据具体情况作出选择。下面我将介绍几个更简单的想法:
第一:
如果您的解决方案是基于会话的,并且您可以持久化会话,那么您可以使用一个临时表,在该表中只能选择order\u id(假设它是orders表中的主键)。或者,如果您想获得每个客户的计数(或其他筛选器),还可以在orders表的order\u id旁边添加第二列customer\u id。
一旦用最少的数据传播了临时表,就可以轻松地计算临时表中的行数,并基于该数字创建分页。现在,当您开始显示页面时,只需选择这些行的子集(使用上面的limit方法),并从临时表order\u id上的orders连接相应的记录(其余的列)。
这有两个好处:
1) 逐页浏览记录会很快,因为它不再查询(大概)大订单表了。
2) 您没有在orders表上使用聚合查询,因为根据记录的数量和设计,这些查询的性能会非常差,并且可能会影响其他并发用户的性能。
请记住,最初创建临时表的速度会慢一些。但如果不将临时表限制为只包含基本列,则速度肯定会更慢。
不过,为初始查询设置一个合理的最大硬限制(临时表记录的数量或某个时间范围)确实是明智的
第二:这是我最喜欢的方法,因为使用这种方法,我不止一次能够解决客户的大型数据库(或特定查询)性能问题。我们讨论的是从50-55秒的查询时间减少到毫秒。这种方法特别不受与数据库可伸缩性相关的减速的影响。
其主要思想是,您可以预先计算所有类型的聚合(即产品的累计总和,或每个客户的订单数等)。为此,您可以创建一个附加表来保存聚合(示例中每个客户的订单数)。
现在是最重要的部分:
必须使用自定义数据库触发器,即在您的情况下可以使用on insert和on delete触发器,这将更新聚合表,并根据是否添加/删除订单来增加/减少特定客户的订单计数。触发器可以在触发表更改之前或之后触发,具体取决于设置触发器的方式。
触发器在数据库上几乎没有开销,因为每个(插入/删除的)记录只会快速触发一次(除非您做了一些愚蠢的事情,例如从某个大表运行count(…)查询,无论如何这都会完全破坏目的)
我通常会做得更细致,每个客户每个月的数量/金额,等等。。。
如果操作得当,聚合计数几乎不可能与实际记录不同步。如果应用程序启用订单的customer\u id更改,则可能还需要添加更新触发器,以便订单的customer id更改将自动反映在aggregates表中。
当然,你还有很多方法可以做到这一点。但上面这两个已经证明是伟大的。一切都取决于环境。。。
我希望我有点抽象的答案能引导你走上正确的道路,因为我只能根据你提出的问题提供的一点信息来回答。。。

相关问题