Sql 通过RStudio中的JDBC连接将大表拆分为2个数据帧

Sql 通过RStudio中的JDBC连接将大表拆分为2个数据帧,sql,r,Sql,R,通过R I连接到远程保存的数据库。我的问题是我的硬件不是很好,数据集包含数千万行,每个表大约有10列。当我运行下面的代码时,在df步骤,我从R得到一个“RAM不足”错误: library(DatabaseConnector) conn <- connect(connectionDetails) df <- querySql(conn,"SELECT * FROM Table1") 库(数据库连接器) connSQL语句 SELECT TOP 5000000 * from Table

通过R I连接到远程保存的数据库。我的问题是我的硬件不是很好,数据集包含数千万行,每个表大约有10列。当我运行下面的代码时,在df步骤,我从R得到一个“RAM不足”错误:

library(DatabaseConnector)
conn <- connect(connectionDetails)
df <- querySql(conn,"SELECT * FROM Table1")
库(数据库连接器)
connSQL语句

SELECT TOP 5000000 * from Table1
不是在做你认为它在做的事

关系表是

关系定义为一组n元组。在数学和关系数据库模型中,集合是唯一的、不重复的项的无序集合,尽管某些DBMS对其数据施加了顺序

从表中选择将生成结果集。结果集在概念上也是无序的,除非并且直到您明确指定它们的顺序,这通常是使用
orderby
子句完成的

使用
top
(或
limit
,具体取决于DBMS)子句将查询返回的记录数(我们称之为“返回的记录”)减少到该查询可以返回的记录数(我们称之为“所选记录”)以下时如果您没有指定一个
order by子句,那么从概念上讲,选择哪个记录作为返回的记录是不可预测和随机的

由于您没有在查询中指定
order by
子句,因此实际上从表中获得了5000000条不可预测的随机记录。每次运行查询时,您可能会得到一组不同的5000000条记录(至少在概念上是这样)

因此,询问如何获得第二个结果集“从n-5000000开始,到最后一行结束”是没有意义的。没有
n
,也没有最后一行。返回记录的选择是不确定的,DBMS不记得以前查询的选择。将此类信息合并到后续查询中的唯一可行方法是将其显式地包含在SQL中,例如在id列上使用
not in
条件,并将第一个查询中的id值嵌入为文本,或者再次执行某种负联接,涉及将id值嵌入为文本。但这显然是不合理的

这里有两种可能的解决方案

1:
订购,带有
限制
偏移

请看下面的图片。首先,为了强调缺乏秩序的观点,请注意以下段落:

使用
LIMIT
时,使用
orderby
子句将结果行约束为唯一顺序非常重要。否则,您将得到查询行的不可预测子集。你可能会问第十行到第二十行,但第十行到第二十行的顺序是什么?顺序未知,除非您指定了
ORDER BY

查询优化器在生成查询计划时考虑了
LIMIT
,因此根据您为
LIMIT
OFFSET
提供的内容,很可能会得到不同的计划(产生不同的行顺序)。因此,使用不同的
限制
/
偏移量
值来选择查询结果的不同子集将产生不一致的结果,除非您使用
顺序执行可预测的结果排序。这不是一个错误;这是SQL不承诺以任何特定顺序交付查询结果这一事实的固有结果,除非使用
orderby
来约束顺序

现在,这个解决方案需要指定一个
orderby
子句来对结果集进行完全排序。一个只对结果集进行部分排序的
order by
子句是不够的,因为它仍然会给一些不可预测性和随机性留下空间

一旦有了
order by
子句,就可以使用相同的
limit
值并增加
offset
值重复查询

大概是这样的:

select * from table1 order by id1, id2, ... limit 5000000 offset 0;
select * from table1 order by id1, id2, ... limit 5000000 offset 5000000;
select * from table1 order by id1, id2, ... limit 5000000 offset 10000000;
...
select * from (select *, row_number() over (id1, id2, ...) rn from table1) t1 where rn>0 and rn<=5000000;
select * from (select *, row_number() over (id1, id2, ...) rn from table1) t1 where rn>5000000 and rn<=10000000;
select * from (select *, row_number() over (id1, id2, ...) rn from table1) t1 where rn>10000000 and rn<=15000000;
...
2:合成编号列并对其进行筛选

可以向select子句添加一列,该列将为结果集提供完整的顺序。通过将此SQL包装在子查询中,然后可以对新列进行筛选,从而实现自己的数据分页。事实上,这个解决方案可能会稍微强大一些,因为理论上可以选择不连续的记录子集,尽管我从未见过有人真正这样做

要计算排序列,可以使用
row\u number()
分区函数

重要的是,您仍然需要指定id列来对分区进行排序。这在任何可能的解决方案下都是不可避免的;总是必须有一些确定性的、可预测的记录顺序来引导无状态的数据分页

大概是这样的:

select * from table1 order by id1, id2, ... limit 5000000 offset 0;
select * from table1 order by id1, id2, ... limit 5000000 offset 5000000;
select * from table1 order by id1, id2, ... limit 5000000 offset 10000000;
...
select * from (select *, row_number() over (id1, id2, ...) rn from table1) t1 where rn>0 and rn<=5000000;
select * from (select *, row_number() over (id1, id2, ...) rn from table1) t1 where rn>5000000 and rn<=10000000;
select * from (select *, row_number() over (id1, id2, ...) rn from table1) t1 where rn>10000000 and rn<=15000000;
...

select*from(select*,row_number()over(id1,id2,…)rn from table 1)t1其中rn>0和rn5000000和rn10000000以及rnI guess在10列中,至少有一列可用于筛选。您甚至可以选择它,以便在(性别、年龄…、地理区域…年/月…)之后更容易执行分析。您使用哪个数据库和哪个驱动程序?你的电脑有多少内存?表在数据库中分配了多少空间(兆字节)?当然,将数据分块是一个很好的解决方案,但了解潜在问题有助于以更好的方式优化结果(直到您对下面bgoldst的答案感到满意。例如,您是否尝试过使用
RODBC
(如果您在Windows上)或直接使用
RJDBC
(由
数据库连接器
调用)?