我正在设计一个多层数据库驱动的web应用程序- SQL关系数据库,Java用于中间服务层,web用于UI。语言并不重要。
中间服务层执行数据库的实际查询。UI只是请求特定的数据,并没有数据库支持的概念。
问题是如何处理大型数据集?UI请求数据,但结果可能很大,可能太大而无法放入内存。例如,一个街道标志应用程序可能有一个服务层:
StreetSign getStreetSign(int identifier)
Collection<StreetSign> getStreetSigns(Street street)
Collection<StreetSign> getStreetSigns(LatLonBox box)
UI层要求获得满足某些条件的所有街道标志。根据条件的不同,结果集可能会很大。UI层可能会将结果分成单独的页面(对于浏览器),或者只是将它们全部呈现出来(服务于Goolge Earth)。潜在的巨大结果集可能是性能和资源问题(内存不足)。
一种解决方案是不返回完全加载的对象(StreetSign对象)。而是返回某种结果集或迭代器,这些结果集或迭代器懒惰地加载每个对象。
另一种解决方案是更改服务API以返回所请求数据的子集:
Collection<StreetSign> getStreetSigns(LatLonBox box, int pageNumber, int resultsPerPage)
当然,UI仍然可以请求一个巨大的结果集:
getStreetSigns(box, 1, 1000000000)
我很好奇这个场景的标准行业设计模式是什么?
发布于 2008-10-23 15:39:05
第一个问题应该是:
用户需要或有能力管理这些数据量?
虽然结果集应该是分页的,但如果它的潜在大小如此之大,答案将是“可能不是”,因此UI不应该尝试显示它。
我在医疗保健系统的J2EE项目中工作,这些项目处理海量的存储数据,字面上是数百万的患者,访问,表单等,一般规则是不显示超过100或200行的任何用户搜索,建议用户,这些标准集产生更多的信息,他可以理解。
实现这一点的方法因项目而异,可以强制UI在启动查询之前向服务层询问查询的大小,或者如果结果集增长太多,也可以从服务层抛出异常(但是,这种方式将服务层与UI的有限实现耦合在一起)。
注意!这并不意味着服务层上的每个方法在其结果大小超过100时都必须抛出异常,这条通用规则只适用于直接显示给用户的结果集,这是将控件放在UI中而不是服务层的更好理由。
发布于 2008-10-23 15:33:56
对于这种情况,我见过的最常见的模式是某种分页,通常在服务器端进行,以减少通过网络发送的信息量。
下面是一个使用表变量(通常比临时表更快)的SQL Server 2000示例以及您的街道标志示例:
CREATE PROCEDURE GetPagedStreetSigns
(
@Page int = 1,
@PageSize int = 10
)
AS
SET NOCOUNT ON
-- This memory-variable table will control paging
DECLARE @TempTable TABLE (RowNumber int identity, StreetSignId int)
INSERT INTO @TempTable
(
StreetSignId
)
SELECT [Id]
FROM StreetSign
ORDER BY [Id]
-- select only those rows belonging to the requested page
SELECT SS.*
FROM StreetSign SS
INNER JOIN @TempTable TT ON TT.StreetSignId = SS.[Id]
WHERE TT.RowNumber BETWEEN ((@Page - 1) * @PageSize + 1)
AND (@Page * @PageSize)
在SQL Server2005中,您可以更巧妙地使用诸如公用表表达式和新的SQL排名函数之类的东西。但是一般的主题是使用服务器只返回属于当前页面的信息。
请注意,如果您允许最终用户对正在查看的数据应用动态过滤器,则此方法可能会变得混乱。
发布于 2008-10-23 14:41:13
我想说的是,如果存在大量数据的可能性,那么就采用分页路线。
您仍然可以设置您不希望它们超过的最大值。
例如,所以使用15,30,50的页面大小...
https://stackoverflow.com/questions/231827
复制相似问题