This article explores and compares various paging techniques in ASP and ASP.NET, including SQL-based methods applicable to both. A key observation is that efficient paging methods often execute a quick query upfront to determine the total record count for page calculation.
Classic ASP
The article “How do I page through a recordset?” serves as an excellent resource for ASP paging. Paging with Recordset.Move() is particularly effective for methods that don’t rely on stored procedures.
Although the article highlights Recordset.GetRows() combined with Recordset.Move() as the top performer—converting a resource-intensive recordset into a lightweight array—using custom business classes often negates the need for GetRows().
Recordset.Move()
This technique utilizes the Move() method to bypass the initial ’n’ rows of the result set, directly accessing the desired page’s first row.
| |
ASP.NET
While ASP.NET offers the DataGrid, its performance suffers as it retrieves all records with each page change. Let’s explore better alternatives:
1) Dataset
This method utilizes DbDataAdapter.Fill(DataSet, Int32, Int32, String) to populate the DataSet with a specific range of records.
| |
However, MSDN (ADO.Net & Paging Through a Query Result) notes:
This might not be the best choice for paging through large query results because, although the DataAdapter fills the target DataTable or DataSet with only the requested records, the resources to return the entire query are still used .. Remember that the database server returns the entire query results even though only one page of records is added to the DataSet.
Indeed, initial tests revealed slow performance with this method, even for nearby pages.
Optimization: Adding a TOP clause to the SELECT query limits the returned records. For instance, requesting the second page with a page size of 10 retrieves only the first 20 records, filling the DataSet with the desired second 10 records instead of the entire table. This enhancement, applicable to DataSet, DataReader, and Recordset, significantly improves performance for closer pages.
2) DataReader
Inspired by ADO’s Recordset.Move() paging, this approach might not be as common but proves effective.
| |
DataReader excels when querying a single table or dealing with read-only, forward-only scenarios. Tests conducted in “A Speed Freak’s Guide to Retrieving Data in ADO.NET” demonstrate its noticeable speed advantage with larger page sizes.
3) Recordset
Utilizing ADO Recordset in ASP.NET might seem unusual but is achievable by referencing “Microsoft ActiveX Data Objects 2.5+”.
| |
SQL Paging
The following methods leverage SQL for paging, suitable for both ASP and ASP.NET.
4) Top Clause
This technique, described in MSDN’s “How To: Page Records in .NET Applications,” utilizes the TOP clause and a DataReader for retrieval.
| |
Caveat: On the last page, if the record count is less than the PageSize, this method always returns the last PageSize records. Skipping records might be necessary to reach the desired data.
5) Row_Number Function
Introduced in SQL Server 2005 and detailed in “Custom Paging in ASP.NET 2.0 with SQL Server 2005,” the ROW_NUMBER() function assigns sequential numbers to query results, facilitating paging.
| |
Performance Comparison
Benchmarking these methods on a table exceeding one million records, retrieving 100 records per page and progressively fetching further pages, yielded interesting results. The test environment: P3.2GHZ CPU, 1GB RAM, Windows XP, SQL Server 2005 Express, and the Microsoft Web Stress Tool.
| Method | 1 to 10000 | 10000 to 100000 | 100000 to 500000 | 500000 to 1000000 |
|---|---|---|---|---|
| Recordset | 601.00 | 1101.06 | 2708.94 | 4750.35 |
| DataSet | 518.79 | 734.94 | 2264.78 | 4463.53 |
| DataReader | 490.12 | 813.29 | 2165.71 | 4094.18 |
| Top Clause | 518.88 | 735.29 | 1881.18 | 4017.88 |
| Row_Number | 381.18 | 466.35 | 801.18 | 1309.76 |
- The
TOPclause optimization brings the performance ofDataReader,DataSet, andRecordsetclose to the dedicatedTop Clausemethod, withDataReaderslightly outperformingDataSet. - While functional, the legacy ADO
Recordsetmight not be the optimal choice in ASP.NET. - The SQL
TOPclause exhibits slightly faster speeds, though SQL Server resource utilization becomes less efficient with distant pages. ROW_NUMBER()emerges as the clear winner for SQL Server 2005 and above.
General Observation: Sorting and searching by indexed columns significantly reduce SQL query costs.
Update: A VB.NET class encapsulating these data access techniques to streamline coding is available in “Write Less & Generic Data Access Code in ADO.NET 2.0.”