我想在浏览器/多页上显示100000条记录,对内存的影响最小。即每页100条记录。 我想来回移动页面。我怀疑是 1.我可以保留记忆中的所有记录吗?这是个好主意吗?
2)我可以为任何页面建立数据库连接/查询吗?如果是这样,怎么写一个查询?
有人可以帮助我..
答案 0 :(得分:8)
在内存中保留如此多的记录通常不是一个好主意。如果多个用户同时访问该应用程序,则内存影响将是巨大的。
我不知道您使用的是什么DBMS,但在MySQL和其他几个版本中,您可以依靠数据库对查询进行分页,例如:
SELECT * FROM MyTable
LIMIT 0, 100
限制之后的第一个数字是偏移量(它将跳过多少条记录),第二个数字是它将获取的记录数。
请记住,这是SQL在每个数据库上没有相同的语法(有些甚至不支持它)。
答案 1 :(得分:3)
我不会将数据保存在内存中(无论是在浏览器中还是在服务应用程序中)。相反,我会使用SQL翻译结果。
如何执行此操作可能是特定于数据库的。有关MySql中的一个示例,请参阅here。其他数据库将存在机制。
答案 2 :(得分:2)
1)不,拥有内存中的所有记录都会破坏拥有数据库的意义。考虑使用可滚动的结果集,这样您就可以获得所需的功能而无需使用SQL。您还可以调整一次提取的记录数,这样就不会加载超出需要的记录。
2)Db连接的创建和销毁成本很高,但任何严重的系统都会集中连接,因此对性能的影响不会那么大。
如果你想获得更多的幻想,你可以完全取消页面,只需在用户滚动列表时加载更多记录。
答案 3 :(得分:1)
这不是一个好主意,因为您正在使浏览器可执行文件保留所有这些。
当我有这样的事情时,使用javascript来渲染页面,并且只是进行了ajax调用以获取下一页。在您获取下一个表时,显示下一个表会有一点延迟,但用户习惯了这一点。
如果你要显示100条记录/页面,请使用json从服务器传递数据,因为javascript可以快速解析它,然后使用innerHTML来放置html,因为DOM在渲染表时要慢得多。
答案 4 :(得分:1)
正如其他人所说,将大量结果存储在内存中并不是一个好主意。查询每个页面的结果肯定是一个更好的方法。要做到这一点,你有两个选择。一种方法是使用DBMS提供的任何数据库特定功能来定位查询结果的特定子部分。另一种方法是使用JDBC提供的泛型方法来实现相同的效果。这可以防止您的代码与特定数据库绑定:
// get a ResultSet from some query
ResultSet results = ...
if (count > 0) {
results.setFetchSize(count + 1);
results.setFetchDirection(ResultSet.FETCH_FORWARD);
results.absolute(count * beginIndex);
}
for (int rowNumber = 0; results.next(); ++rowNumber) {
if (count > 0 && rowNumber > count) {
break;
}
// process the ResultSet below
...
}
使用像Spring JDBC或Hibernate这样的库可以使这更容易。
答案 5 :(得分:0)
在许多SQL语言中,你有一个LIMIT(mysql,...)或OFFSET(mssql)的概念。 您可以使用这种方法限制每页行数
答案 6 :(得分:0)
取决于数据。如果你正在缓存,100k int可能不会太糟糕。
T-SQL有SET @@ ROWCOUNT = 100来限制返回的记录数量。
但要做到正确并返回总页数,您需要更高级的分页SPROC。
这是一个非常热门的主题,有很多方法可以做到。
这是我写的一篇旧文章的样本
CREATE PROCEDURE Objects_GetPaged
(
@sort VARCHAR(255),
@Page INT,
@RecsPerPage INT,
@Total INT OUTPUT
)
AS
SET NOCOUNT ON
--Create a temporary table
CREATE TABLE #TempItems
(
id INT IDENTITY,
memberid int
)
INSERT INTO #TempItems (memberid)
SELECT Objects.id
FROM Objects
ORDER BY CASE @sort WHEN 'Alphabetical' THEN Objects.UserName ELSE NULL END ASC,
CASE @sort WHEN 'Created' THEN Objects.Created ELSE NULL END DESC,
CASE @sort WHEN 'LastLogin' THEN Objects.LastLogin ELSE NULL END DESC
SELECT @Total=COUNT(*) FROM #TempItems
-- Find out the first and last record we want
DECLARE @FirstRec int, @LastRec int
SELECT @FirstRec = (@Page - 1) * @RecsPerPage
SELECT @LastRec = (@Page * @RecsPerPage + 1)
SELECT *
FROM #TempItems
INNER JOIN Objects ON(Objects.id = #TempItems.id)
WHERE #TempItems.ID > @FirstRec AND #TempItems.ID < @LastRec
ORDER BY #TempItems.Id
答案 7 :(得分:0)
我建议您选择使用CachedRowSet。
CachedRowSet对象是用于将其行缓存在内存中的数据行的容器,这使得可以在不始终连接到其数据源的情况下进行操作。
CachedRowSet对象是一个断开连接的行集,这意味着它只是短暂地使用了与其数据源的连接。它在读取数据时连接到它的数据源,用行填充自己,并在将更改传播回其底层数据源时再次连接。
因为CachedRowSet对象将数据存储在内存中,所以它在任何时候都可以包含的数据量由可用内存量决定。为了解决这个限制,CachedRowSet对象可以从一个名为pages的数据块中的ResultSet对象中检索数据。为了利用此机制,应用程序使用方法setPageSize设置要包含在页面中的行数。换句话说,如果页面大小设置为5,则将一次从数据源中提取一行五行数据。应用程序还可以选择设置一次可以获取的最大行数。如果将最大行数设置为零,或者未设置最大行数,则一次可以获取的行数没有限制。
设置属性后,必须使用populate方法或execute方法使用数据填充CachedRowSet对象。以下代码行演示了如何使用populate方法。请注意,此版本的方法采用两个参数,一个ResultSet句柄和ResultSet对象中的行,从中开始检索行。
CachedRowSet crs = new CachedRowSetImpl();
crs.setMaxRows(20);
crs.setPageSize(4);
crs.populate(rsHandle, 10);
当这段代码运行时,crs将从第10行开始用rsHandle填充四行。
在类似的路径上,您可以构建一个策略来对JSP上的数据进行分页,依此类推。