使用分页获取大量数据

23c0lvtd  于 2021-06-20  发布在  Mysql
关注(0)|答案(3)|浏览(334)

比如说我有一个 Cloud 环境与环境 Client 我想把大量的数据从云端同步到客户端。假设我在云中有一个名为 Files 我希望客户机环境中存在完全相同的表。
现在让我们假设一些事情:
文件桌很大。
文件中每一行的数据可以随时更新,并且具有 last-update 列。
我想获取delta,并确保我在两种环境中都是相同的。
我的解决方案:
我首先进行完全同步,将所有条目返回给客户端。
我留着钥匙 LastSync 在客户端环境中的时间,并保持从客户端同步增量 LastSync 时间。
我使用分页进行完全同步和增量同步:客户机将发出第一个请求来获取 Count delta的结果和 Page Size 每一个请求。
例如,计数:

SELECT COUNT(*) FROM files WHERE last_update > @LastSyncTime

页面获取:

SELECT col1, col2..
FROM files 
WHERE last_update > @LastSyncTime
ORDER BY files.id
LIMIT @LIMIT 
OFFSET @OFFSET

我的问题是:
例如,如果第一次提取 Count fetch)将需要一些时间(例如几分钟),在这段时间内,更多的条目被更新并添加到 last-update 取回。
例如:
伯爵给了他100个条目 last-update 1000 seconds .
获取数据时更新了1个条目 Count .
现在 last-update 1000 seconds 将提供101个条目。
页面获取将只从order by的101中获取100个条目 id 1个条目丢失且未同步到客户端
我尝试过两种其他选择:
与同步 from-to 的日期限制 last-update .
订购人 last-update 而不是 id 列。
我认为这两种选择都有问题。

eh57zj3b

eh57zj3b1#

不要使用 OFFSET 以及 LIMIT ; 从正常到缓慢再到缓慢。相反,要记住“你离开的地方” last_update 这样才能更有效率。更多讨论
由于datetime可能有重复,所以要灵活地确定一次要做多少行。
继续运行。不要使用cron,除非用作“keep alive”。
不需要初始副本;这个代码是为你做的。
重要的是 INDEX(last_update) 代码如下:

-- Initialize.  Note: This subtract is consistent with the later compare. 
SELECT @left_off := MIN(last_update) - INTERVAL 1 DAY
    FROM tbl;

Loop:

    -- Get the ending timestamp:
    SELECT @cutoff := last_update FROM tbl
         WHERE last_update > @left_off
         ORDER BY last_update
         LIMIT 1  OFFSET 100;   -- assuming you decide to do 100 at a time
    -- if no result, sleep for a while, then restart

    -- Get all the rows through that timestamp
    -- This might be more than 100 rows
    SELECT * FROM tbl
        WHERE last_update > @left_off
          AND last_update <= @cutoff
        ORDER BY last_update
    -- and transfer them

    -- prep for next iteration
    SET @left_off := @cutoff;

Goto Loop
``` `SELECT @cutoff` 它是对索引中100个连续行的简短扫描。 `SELECT *` 进行繁重的搬运,所需时间与行数成比例——不需要额外的开销 `OFFSET` . 读取100行数据大约需要1秒(假设磁盘旋转,非缓存数据)。
而不是一开始 `COUNT(*)` ,我会从 `MAX(last_update)` 因为代码的其余部分是基于 `last_update` . 这个查询是“即时的”,因为它只需要探测索引的末尾。但我说你根本不需要这个!
一个可能的错误:如果“source”中的行可以被删除,您如何识别它?
6yjfywim

6yjfywim2#

你的方法涵盖了很多变通方法,你走错了方向。
开始考虑数据库复制,它将抽象所有这些解决方法,并将为您提供解决此类问题的工具。
一篇关于mysql server最近的组复制的优秀文章:https://www.digitalocean.com/community/tutorials/how-to-configure-mysql-group-replication-on-ubuntu-16-04

cnh2zyt3

cnh2zyt33#

根据数据的大小,如果数据是“公共”的,或者可以在多个客户机之间使用,那么拆分数据可能会有所帮助。例如,创建每日的“delta”完整数据集并缓存它们。这样,数据库就不需要在第一次加载时反复查询每个客户机需要的数据。
尽量减少对大数据表的访问(如果数据没有任何变化,则在异地缓存)。
卸载和缓存经常使用和查询的数据。因此可以减少sql查询的数量。
在上创建索引 last_update 以及 id 应该有助于加快从数据库中获取实时增量线的速度。
可能的解决方案:
每当有新项目时,数据库每x次创建一个小时/完整集。
客户机在第一次从缓存获取数据时获得“每日增量/每小时增量”。
客户机直接从数据库获取自上次增量“最新项”以来的所有项。
可能有帮助:
使用查询通知更新cache:mssql query sql server中的通知
使用时 MySQL :在mysql中通知事件侦听器

相关问题