我的SQL表太大了:通过分页/分割结果来检索数据



这是一个设计/算法问题以下是我的场景概要:

  • 我有一个大的数据表(比如说,500万行),我称之为汽车
  • 然后我有一个应用程序,它在这个Cars表上执行SELECT *,获取所有数据并将其打包到一个数据文件中(然后将其上传到某个地方)
  • 我的应用程序生成的这个数据文件表示一个快照,即表在某个时刻的样子
  • 但是,表Cars会由另一个进程偶尔更新,无论应用程序当前是否从表中生成包。(当前没有同步。)

我的问题

此表汽车变得太大,无法进行单个SELECT *对抗。当我的应用程序一次检索所有这些数据时,它会很快耗尽我机器的内存容量(比如说2GB)。此外,简单地用LIMIT或OFFSET执行链式SELECT会使同步条件失败:表经常更新,我不能在SELECT调用之间更改数据。

我要查找的内容

一种将整个表拉入内存容量小于数据的应用程序的方法,假设数据大小可能接近无穷大。特别是,如何实现SQL选择的分页/分段效果?即使用页码进行重复调用以检索下一段数据。理想的解决方案允许数据大小的可扩展性。

(为了简化我的场景,我们可以假设,当给定一段数据时,应用程序可以处理/写入它,然后在请求下一段数据之前释放所用的内存。)

你能提供的任何建议都是非常有用的。谢谢

编辑:根据要求,我的实现使用C#.NET 4.0&MSSQL 2008。

编辑#2:这不是SQL命令问题。这是一个与设计模式相关的问题:对大表执行分页SELECT的策略是什么?(尤其是当所述表接收到一致更新时。)

您使用的是什么数据库?例如,在MySQL中,以下将从第40行开始选择20行,但这是仅限MySQL的子句(编辑:Postgres似乎也允许这样做)

 select * from cars limit 20 offset 40

如果您想要一个"快照"效果,您必须将数据复制到不会更新的保存表中。您可以通过各种类型的更改跟踪来完成一些不错的事情,但这不是您所说的想要的。如果您需要一个精确表状态的快照,那么获取快照并将其写入一个单独的表,然后使用限制和偏移量(或其他)来创建页面。

在500万行的情况下,我认为这可能是需要修改的设计要求。。。如果你有2000个客户端都在拍摄500万个行快照,如果你不小心的话,你就会开始出现一些大小问题。

您应该提供结果数据文件格式的详细信息。根据格式的不同,这可能直接在您的数据库中实现,不涉及任何应用程序代码,例如mysql:

SELECT * INTO OUTFILE "c:/mydata.csv"
FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
LINES TERMINATED BY "n"
FROM my_table;

对于oracle,将有导出,对于sqlserver/sybase,将是BCP等。

或者,可以通过流式传输数据来实现,而无需将其全部保存在内存中,这将因应用程序语言而异。

在分页方面,简单的选择是在您使用的任何rdbms中只使用limit子句(如果是mysql)或equivalent,但这是最后的手段:

select * from myTable order by ID LIMIT 0,1000
select * from myTable order by ID LIMIT 1000,1000
select * from myTable order by ID LIMIT 2000,1000
...

这将选择1000行块中的数据。

看看这篇关于使用limit和offset从sql查询中创建分页结果的文章。

http://www.petefreitag.com/item/451.cfm

你必须首先:

SELECT * from Cars Limit 10

然后

SELECT * from Cars limit 10 offset 10

等等。你必须找出最好的页码。

最新更新