【问题标题】:Display 100000 records on browser / multiple pages在浏览器/多个页面上显示 100000 条记录
【发布时间】:2010-10-21 02:04:45
【问题描述】:

我想在浏览器/多个页面上显示 100000 条记录,对内存的影响最小。即每页 100 条记录。 我想来回移动页面。我的疑惑是
1. 我可以保留内存中的所有记录吗?这是个好主意吗?

2) 我可以为每页建立数据库连接/查询吗?如果是这样如何编写查询?

谁能帮帮我..

【问题讨论】:

    标签: java jsp jdbc


    【解决方案1】:

    在内存中维护这么多记录通常不是一个好主意。如果应用同时被多个用户访问,内存影响会很大。

    我不知道您使用的是什么 DBMS,但在 MySQL 和其他几个数据库中,您可以依靠 DB 进行分页查询,例如:

    SELECT * FROM MyTable
    LIMIT 0, 100
    

    limit 之后的第一个数字是偏移量(它将跳过多少条记录),第二个是它将获取的记录数。

    请记住,SQL 在每个 DB 上都没有相同的语法(有些甚至不支持)。

    【讨论】:

      【解决方案2】:

      我不会将数据保存在内存中(无论是在浏览器中还是在服务应用程序中)。相反,我会使用 SQL 对结果进行分页。

      如何做到这一点可能是特定于数据库的。有关 MySql 中的一个示例,请参见 here。其他数据库将存在机制。

      【讨论】:

        【解决方案3】:

        1) 不,将所有记录都保存在内存中有点违背了拥有数据库的意义。考虑拥有一个可滚动的结果集,这样您就可以获得所需的功能,而无需使用 SQL。您还可以调整一次提取的记录数,以免加载的记录超出您的需要。

        2) 创建和销毁数据库连接的成本很高,但任何严重的系统都会将连接池化,因此对性能的影响不会那么大。

        如果您想要更花哨,您可以完全取消页面,只需在用户滚动列表时加载更多记录。

        【讨论】:

          【解决方案4】:

          这不是一个好主意,因为您正在让浏览器可执行文件包含所有这些。

          当我有这样的事情要做时,我使用 javascript 来呈现页面,然后进行 ajax 调用以获取下一页。在您获取下一个表时,显示下一个表会有一点延迟,但用户已经习惯了。

          如果你显示 100 条记录/页,使用 json 从服务器传递数据,因为 javascript 可以快速解析它,然后使用 innerHTML 放置 html,因为 DOM 在呈现表格时要慢得多。

          【讨论】:

          • 你为每个页面显示建立了一个数据库连接?
          • mySQL 建立非常快的连接,但如果担心性能,您也可以拥有一个 db 连接池,所以是的,每个页面都有一个 db 连接,特别是因为您不知道在下一页已移至。
          【解决方案5】:

          正如其他人在这里提到的,将大量结果列表存储在内存中并不是一个好主意。查询每个页面的结果无疑是一种更好的方法。为此,您有两种选择。一种是使用您的 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 这样的库可以使这更容易。

          【讨论】:

            【解决方案6】:

            在许多 SQL 语言中,您都有 LIMIT (mysql, ...) 或 OFFSET (mssql) 的概念。 您可以使用这种东西来限制每页的行数

            【讨论】:

              【解决方案7】:

              取决于数据。如果您正在缓存它,100k int 可能还不错。

              T-SQL 有 SET @@ROWCOUNT = 100 来限制返回的记录数量。

              但要正确执行并返回总页数,您需要更高级的分页 SPROC。

              这是一个非常热门的话题,有很多方法可以做到。

              这是我写的一个旧 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
              

              【讨论】:

                【解决方案8】:

                我建议您选择使用 CachedRowSet 。

                CachedRowSet 对象是数据行的容器,将其行缓存在内存中,这样就可以在不始终连接到其数据源的情况下进行操作。

                CachedRowSet 对象是一个断开连接的行集,这意味着它仅短暂地使用与其数据源的连接。它在读取数据以用行填充自身时连接到其数据源,并在将更改传播回其底层数据源时再次连接。

                因为 CachedRowSet 对象将数据存储在内存中,所以它在任何时候可以包含的数据量取决于可用的内存量。为了解决这个限制,CachedRowSet 对象可以从 ResultSet 对象中以数据块(称为页面)的形式检索数据。为了利用这种机制,应用程序使用 setPageSize 方法设置要包含在页面中的行数。换句话说,如果页面大小设置为 5,则一次会从数据源中获取包含 5 行数据的块。应用程序还可以选择设置一次可以获取的最大行数。如果最大行数设置为零,或者没有设置最大行数,则一次可以提取的行数没有限制。

                设置属性后,必须使用方法填充或执行方法向 CachedRowSet 对象填充数据。以下代码行演示了使用方法填充。请注意,此版本的方法有两个参数,一个 ResultSet 句柄和 ResultSet 对象中的行,从该行开始检索行。

                CachedRowSet crs = new CachedRowSetImpl();
                crs.setMaxRows(20);
                crs.setPageSize(4);
                crs.populate(rsHandle, 10);
                

                当此代码运行时,crs 将从 rsHandle 中填充四行,从第十行开始。

                在类似的路径上,您可以建立一个策略,在 JSP 上对数据进行分页等等。

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2015-03-09
                  • 2014-06-12
                  • 1970-01-01
                  • 1970-01-01
                  • 2011-07-13
                  • 1970-01-01
                  • 2014-05-07
                  • 1970-01-01
                  相关资源
                  最近更新 更多