Details
-
Type:
Improvement
-
Status:
Closed
-
Priority:
Major
-
Resolution: Duplicate
-
Affects Version/s: 1.0 RC2
-
Fix Version/s: 1.1
-
Component/s: Paging/Sorting
-
Labels:None
Description
====
imported from sf tracker
id 1026408
submitted by Ivan Markov - ivan_markov
http://sourceforge.net/tracker/index.php?func=detail&group_id=73068&atid=536613&aid=1026408
====
Smart Paging
------------
Smart paging refers to the ability of DT to deal with large lists of data. The problem with the current DT approach is that:
a) The whole (potentially large) list of data has to be created for the DT tag, occupying lots of memory.
b) If the list contains 1000s of records, populated with data from a SQL Server (99% of the cases, I would say), you have huge network traffic between the webapp and the server. Our code is especially useful for servers like Oracle & MySQL which have built-in means to return only a subset of DB cursor's content.
There's one solution + one enhancement on the forums already (issue #1013526), so why a third one?
We didn't like in the earlier proposal that it deals with intercepting DT's request and parsing DT's request parameters, which seems a bit hacky. Also, we avoid the complications of parsing parameters when there is > 1 table tag on the page. Not to mention that the older proposal does not deal with full list sorting, or does it?
Instead, we introduced a new interface, DataProvider. It has two methods:
- List getData(int unsortedOffset, int unsortedLength, int recordOffset, int pageSize, String sortedColumnName, boolean sortOrderAscending);
- int getDataCount();
The first two parameters unsortedOffset & unsortedLength are only needed for supporting DT's setOffset()/setLength() features.
In our patch, DataProvider is used as a "callback" into user's code. The user is supposed to implement the two methods of this interface.
The code in TableTag and its supporting classes is changed in a way that, for each response where DT is rendered,
a) One call is issued to DataProvider.getDataCount(), which retrieves the total number of rows in the data set (needed for DT to calculate the number of pages).
b) One call is issued to DataProvider.getData(), with the current page, page size & sorting info.
A sample implementation of user-supplied JDBC DataProvider follows, in pseudocode. Some JDBC exception handling stuff omitted.
<%
request.setAttribute("list", new DataProvider() {
List getData(int unsortedOffset, int unsortedLength, int recordOffset, int pageSize, String sortedColumnName, boolean sortOrderAscending) {
Connection con = <app-specific way to get connection>;
PreparedStatement ps = con.prepareStatement("SELECT * FROM MyTable ORDER BY ? LIMIT ?, ?"):
ps.setString(1, sortedColumnName);
ps.setInt(2, recordOffset);
ps.setInt(3, pageSize);
//etc..
ResultSet rs = con.execute();
return <app-specific way of getting List from ResultSet; Maybe use RowSet instead of List?>;
}
int getDataCount() {
Connection con = <app-specific way to get connection>;
PreparedStatement ps = con.prepareStatement("SELECT count(*) FROM MyTable"):
ResultSet rs = con.execute();
rs.next();
return rs.getInt(1);
}
});
%>
(DataProvider implementation code can be moved to Struts Controller/Action, depending on the MVC framework used, in order not to polute the JSP code with Java scriptlets.)
Smart Paging Compatibility
--------------------------
We tried to change DT's code so that all older code to continue to work.
If user has provided an old-style List containing all the data, DT will automatically wrap it with a ListDataProvider.
Current DT functionality (full-list sorting, decorations, multiple tables per page, etc.) is supported, except for these two cases:
a) Full list(not page) sorting by a decorated column - sorting is done without regarding the decorator.
b) Full list sorting by a column with no "property" attribute (static or implicit object call via servlet) - no sorting is performed at all.
imported from sf tracker
id 1026408
submitted by Ivan Markov - ivan_markov
http://sourceforge.net/tracker/index.php?func=detail&group_id=73068&atid=536613&aid=1026408
====
Smart Paging
------------
Smart paging refers to the ability of DT to deal with large lists of data. The problem with the current DT approach is that:
a) The whole (potentially large) list of data has to be created for the DT tag, occupying lots of memory.
b) If the list contains 1000s of records, populated with data from a SQL Server (99% of the cases, I would say), you have huge network traffic between the webapp and the server. Our code is especially useful for servers like Oracle & MySQL which have built-in means to return only a subset of DB cursor's content.
There's one solution + one enhancement on the forums already (issue #1013526), so why a third one?
We didn't like in the earlier proposal that it deals with intercepting DT's request and parsing DT's request parameters, which seems a bit hacky. Also, we avoid the complications of parsing parameters when there is > 1 table tag on the page. Not to mention that the older proposal does not deal with full list sorting, or does it?
Instead, we introduced a new interface, DataProvider. It has two methods:
- List getData(int unsortedOffset, int unsortedLength, int recordOffset, int pageSize, String sortedColumnName, boolean sortOrderAscending);
- int getDataCount();
The first two parameters unsortedOffset & unsortedLength are only needed for supporting DT's setOffset()/setLength() features.
In our patch, DataProvider is used as a "callback" into user's code. The user is supposed to implement the two methods of this interface.
The code in TableTag and its supporting classes is changed in a way that, for each response where DT is rendered,
a) One call is issued to DataProvider.getDataCount(), which retrieves the total number of rows in the data set (needed for DT to calculate the number of pages).
b) One call is issued to DataProvider.getData(), with the current page, page size & sorting info.
A sample implementation of user-supplied JDBC DataProvider follows, in pseudocode. Some JDBC exception handling stuff omitted.
<%
request.setAttribute("list", new DataProvider() {
List getData(int unsortedOffset, int unsortedLength, int recordOffset, int pageSize, String sortedColumnName, boolean sortOrderAscending) {
Connection con = <app-specific way to get connection>;
PreparedStatement ps = con.prepareStatement("SELECT * FROM MyTable ORDER BY ? LIMIT ?, ?"):
ps.setString(1, sortedColumnName);
ps.setInt(2, recordOffset);
ps.setInt(3, pageSize);
//etc..
ResultSet rs = con.execute();
return <app-specific way of getting List from ResultSet; Maybe use RowSet instead of List?>;
}
int getDataCount() {
Connection con = <app-specific way to get connection>;
PreparedStatement ps = con.prepareStatement("SELECT count(*) FROM MyTable"):
ResultSet rs = con.execute();
rs.next();
return rs.getInt(1);
}
});
%>
(DataProvider implementation code can be moved to Struts Controller/Action, depending on the MVC framework used, in order not to polute the JSP code with Java scriptlets.)
Smart Paging Compatibility
--------------------------
We tried to change DT's code so that all older code to continue to work.
If user has provided an old-style List containing all the data, DT will automatically wrap it with a ListDataProvider.
Current DT functionality (full-list sorting, decorations, multiple tables per page, etc.) is supported, except for these two cases:
a) Full list(not page) sorting by a decorated column - sorting is done without regarding the decorator.
b) Full list sorting by a column with no "property" attribute (static or implicit object call via servlet) - no sorting is performed at all.
-
- displaytag-1.0-rc1-pdf_paging_exclude_columnhref.diff
- 24/Nov/04 5:13 AM
- 34 kB
- Bastian Bowe
-
Hide
- dt_pdf_paging_java.zip
- 25/Sep/04 4:40 AM
- 149 kB
- fabrizio giustina
-
- java/CVS/Entries 0.0 kB
- java/CVS/Repository 0.0 kB
- java/CVS/Root 0.1 kB
- java/CVS/vssver.scc 0.1 kB
- java/org/apache/CVS/Entries 0.0 kB
- java/org/apache/CVS/Repository 0.0 kB
- java/org/apache/CVS/Root 0.1 kB
- java/org/apache/CVS/vssver.scc 0.1 kB
- java/org/apache/taglibs/CVS/Entries 0.0 kB
- java/org/apache/taglibs/CVS/Repository 0.0 kB
- java/org/apache/taglibs/CVS/Root 0.1 kB
- java/org/apache/taglibs/CVS/vssver.scc 0.1 kB
- java/org/.../display/ColumnDecorator.java 0.8 kB
- java/org/apache/.../display/CVS/Entries 0.2 kB
- java/org/apache/.../display/CVS/Repository 0.0 kB
- java/org/apache/taglibs/display/CVS/Root 0.1 kB
- java/org/apache/.../display/CVS/vssver.scc 0.1 kB
- java/org/apache/.../display/Decorator.java 1 kB
- java/org/.../display/TableDecorator.java 1 kB
- java/org/apache/.../display/vssver.scc 0.1 kB
- java/org/CVS/Entries 0.0 kB
- java/org/CVS/Repository 0.0 kB
- java/org/CVS/Root 0.1 kB
- java/org/CVS/vssver.scc 0.1 kB
- java/org/displaytag/CVS/Entries 0.1 kB
- java/org/displaytag/CVS/Repository 0.0 kB
- java/org/displaytag/CVS/Root 0.1 kB
- java/org/displaytag/CVS/vssver.scc 0.1 kB
- java/org/.../decorator/ColumnDecorator.java 1.0 kB
- java/org/displaytag/.../CVS/Entries 0.2 kB
-
- dt_pdf_paging.diff
- 25/Sep/04 4:39 AM
- 74 kB
- fabrizio giustina
-
Hide
- OptimizedPaginationIteration.1.0-RC2.zip
- 12/Nov/04 5:39 PM
- 16 kB
- James Schopp
-
- TableTag.java 56 kB
- SmartListHelper.java 11 kB
-
Hide
- OptimizedPaginationIteration.zip
- 15/Oct/04 2:12 PM
- 15 kB
- James Schopp
-
- SmartListHelper.java 12 kB
- TableTag.java 54 kB
Activity
Hide
Permalink
fabrizio giustina
added a comment -
diff
Show
fabrizio giustina
added a comment - diff
Show
fabrizio giustina
added a comment - full source snapshot
Hide
James Schopp
added a comment -
While I don't want to "boil the ocean" with requirements, this solution doesn't meet all needs (at least mine...). For example :
1) our backend is a mainframe that feeds us data in sets - you cannot know the full record size without first reading all the sets, which I don't want to have to do.
2) the size of each set is controlled by the backend, not DT. So, although DT might display 10 records per page, we are forced to get data back in 100-record sets. 1 data set can back 10 DT pages. This means each page-hit does NOT coincide with a DB-hit.
3) the "marker" for fetching the next data set is returned to us by the previous set - it is not sufficient just to know what page you are on. In order to get the "marker" for the 10th page, you must first traverse the previous 9.
4) One of the databases we are using is MS SQL Server, which although it does have the "top" select attribute to get the first 100, it cannot for instance grab the middle 100. To do this we rely on sorting the data by specific columns, the specify a ">" where clause to remove the first X records, then use the top specifier to get the first Y records. This has the overall effect of getting the middle N records, but seriously limits our sorting capability.
I have found yet another solution (which does NOT exclude the solution you all provide):
We have gotten around alot of these issues by creating a "PagingList" List implementation which has the ability to load and unload data as necessary. So, you if iterate the list, it will load data as needed, but then unload say records 1-100 if you are currently on record 200. It also caches the markers mentioned above, so that after the first sequential access, it is randomly accessible from then on. The markers are definable by the back end, so if the system is MySQL, it could be as simple as "page number", but if the backend is a mainframe, it could be a complex object.
I have implemented this list with DT, and it only required a few changes to the DT source - which are in reality just optimizations. The changes are only to stop DT from constantly iterating over the entire list, which in my case caused the entire dataset to be loaded (very large).
THESE OPTIMIZATIONS ARE THEREFORE BENEFICIAL TO ALL LISTS, not just my "special" lists. This means it *should* also work
The optimizations only "kick in" if the table is NOT full-list sorted, and the object is actually of type "List" (since it appears that in theory DT can make tables out of other collections too).
I made these ontop of 1.0 rc1
I will attach them below.
1) our backend is a mainframe that feeds us data in sets - you cannot know the full record size without first reading all the sets, which I don't want to have to do.
2) the size of each set is controlled by the backend, not DT. So, although DT might display 10 records per page, we are forced to get data back in 100-record sets. 1 data set can back 10 DT pages. This means each page-hit does NOT coincide with a DB-hit.
3) the "marker" for fetching the next data set is returned to us by the previous set - it is not sufficient just to know what page you are on. In order to get the "marker" for the 10th page, you must first traverse the previous 9.
4) One of the databases we are using is MS SQL Server, which although it does have the "top" select attribute to get the first 100, it cannot for instance grab the middle 100. To do this we rely on sorting the data by specific columns, the specify a ">" where clause to remove the first X records, then use the top specifier to get the first Y records. This has the overall effect of getting the middle N records, but seriously limits our sorting capability.
I have found yet another solution (which does NOT exclude the solution you all provide):
We have gotten around alot of these issues by creating a "PagingList" List implementation which has the ability to load and unload data as necessary. So, you if iterate the list, it will load data as needed, but then unload say records 1-100 if you are currently on record 200. It also caches the markers mentioned above, so that after the first sequential access, it is randomly accessible from then on. The markers are definable by the back end, so if the system is MySQL, it could be as simple as "page number", but if the backend is a mainframe, it could be a complex object.
I have implemented this list with DT, and it only required a few changes to the DT source - which are in reality just optimizations. The changes are only to stop DT from constantly iterating over the entire list, which in my case caused the entire dataset to be loaded (very large).
THESE OPTIMIZATIONS ARE THEREFORE BENEFICIAL TO ALL LISTS, not just my "special" lists. This means it *should* also work
The optimizations only "kick in" if the table is NOT full-list sorted, and the object is actually of type "List" (since it appears that in theory DT can make tables out of other collections too).
I made these ontop of 1.0 rc1
I will attach them below.
Show
James Schopp
added a comment - While I don't want to "boil the ocean" with requirements, this solution doesn't meet all needs (at least mine...). For example :
1) our backend is a mainframe that feeds us data in sets - you cannot know the full record size without first reading all the sets, which I don't want to have to do.
2) the size of each set is controlled by the backend, not DT. So, although DT might display 10 records per page, we are forced to get data back in 100-record sets. 1 data set can back 10 DT pages. This means each page-hit does NOT coincide with a DB-hit.
3) the "marker" for fetching the next data set is returned to us by the previous set - it is not sufficient just to know what page you are on. In order to get the "marker" for the 10th page, you must first traverse the previous 9.
4) One of the databases we are using is MS SQL Server, which although it does have the "top" select attribute to get the first 100, it cannot for instance grab the middle 100. To do this we rely on sorting the data by specific columns, the specify a ">" where clause to remove the first X records, then use the top specifier to get the first Y records. This has the overall effect of getting the middle N records, but seriously limits our sorting capability.
I have found yet another solution (which does NOT exclude the solution you all provide):
We have gotten around alot of these issues by creating a "PagingList" List implementation which has the ability to load and unload data as necessary. So, you if iterate the list, it will load data as needed, but then unload say records 1-100 if you are currently on record 200. It also caches the markers mentioned above, so that after the first sequential access, it is randomly accessible from then on. The markers are definable by the back end, so if the system is MySQL, it could be as simple as "page number", but if the backend is a mainframe, it could be a complex object.
I have implemented this list with DT, and it only required a few changes to the DT source - which are in reality just optimizations. The changes are only to stop DT from constantly iterating over the entire list, which in my case caused the entire dataset to be loaded (very large).
THESE OPTIMIZATIONS ARE THEREFORE BENEFICIAL TO ALL LISTS, not just my "special" lists. This means it *should* also work
The optimizations only "kick in" if the table is NOT full-list sorted, and the object is actually of type "List" (since it appears that in theory DT can make tables out of other collections too).
I made these ontop of 1.0 rc1
I will attach them below.
Hide
James Schopp
added a comment -
Here is the full source for TableTag and SmartListHelper in order to add the iteration optimizations on non-full-page sorting lists.
Show
James Schopp
added a comment - Here is the full source for TableTag and SmartListHelper in order to add the iteration optimizations on non-full-page sorting lists.
Hide
fabrizio giustina
added a comment -
I tested james implementation, many details are not taken into account:
- the "export full list" doesn't work anymore, list is always splitted
- listIndex/viewIndex in tableDecorator are now wrong
- optimization is only done when the underlining object is a list, is there any way to make it more generic (using commons-collections utils)?
Some more tests needed for:
- are offset/length attributes considered in smart paging?
- when offset is set, column body for rows < offset should not be executed
- the "export full list" doesn't work anymore, list is always splitted
- listIndex/viewIndex in tableDecorator are now wrong
- optimization is only done when the underlining object is a list, is there any way to make it more generic (using commons-collections utils)?
Some more tests needed for:
- are offset/length attributes considered in smart paging?
- when offset is set, column body for rows < offset should not be executed
Show
fabrizio giustina
added a comment - I tested james implementation, many details are not taken into account:
- the "export full list" doesn't work anymore, list is always splitted
- listIndex/viewIndex in tableDecorator are now wrong
- optimization is only done when the underlining object is a list, is there any way to make it more generic (using commons-collections utils)?
Some more tests needed for:
- are offset/length attributes considered in smart paging?
- when offset is set, column body for rows < offset should not be executed
Hide
Anonymous
added a comment -
Shouldn't the affected version be 1.0 RC1, since James mentioned in his comment that he made those changes ontop of 1.0 rc1? Where and when can a Smart Paging RC2 version be published?
Show
Anonymous
added a comment - Shouldn't the affected version be 1.0 RC1, since James mentioned in his comment that he made those changes ontop of 1.0 rc1? Where and when can a Smart Paging RC2 version be published?
Hide
James Schopp
added a comment -
Fabrizio has apparently begun incorporating the optimizations into the RC2 code, but it is not complete (it still iterates over the whole list when viewing just the first page).
I have made the modifications again, ontop of RC2, and will include them here in a zip file
thanks, james
I have made the modifications again, ontop of RC2, and will include them here in a zip file
thanks, james
Show
James Schopp
added a comment - Fabrizio has apparently begun incorporating the optimizations into the RC2 code, but it is not complete (it still iterates over the whole list when viewing just the first page).
I have made the modifications again, ontop of RC2, and will include them here in a zip file
thanks, james
Hide
James Schopp
added a comment -
Here's the file to complete the optimization stuff for RC2.
It works with offset and length params also. It still requires that the underlying list actually be a true "List" though.
It works with offset and length params also. It still requires that the underlying list actually be a true "List" though.
Show
James Schopp
added a comment - Here's the file to complete the optimization stuff for RC2.
It works with offset and length params also. It still requires that the underlying list actually be a true "List" though.
Hide
fabrizio giustina
added a comment -
sorry, but the new files still seem not to be related to the current version of TableTag.java (a few things committed recently are missed) and I wasn't able to apply the changes.
Could you please recreate the patch against the current cvs version and submit a real patch instead of the full java file?
If you use Eclipse, you can generate a patch easily: right click on a directory or source file and select Team -> Create patch (choose "unified format" when you will be asked). You need the project connected to cvs for this.
I applied only parts of the previous patch because there were some problems with column bodies and row indexes. I will rerun unit tests for the new patch and judge if I can commit it. Thanks.
Could you please recreate the patch against the current cvs version and submit a real patch instead of the full java file?
If you use Eclipse, you can generate a patch easily: right click on a directory or source file and select Team -> Create patch (choose "unified format" when you will be asked). You need the project connected to cvs for this.
I applied only parts of the previous patch because there were some problems with column bodies and row indexes. I will rerun unit tests for the new patch and judge if I can commit it. Thanks.
Show
fabrizio giustina
added a comment - sorry, but the new files still seem not to be related to the current version of TableTag.java (a few things committed recently are missed) and I wasn't able to apply the changes.
Could you please recreate the patch against the current cvs version and submit a real patch instead of the full java file?
If you use Eclipse, you can generate a patch easily: right click on a directory or source file and select Team -> Create patch (choose "unified format" when you will be asked). You need the project connected to cvs for this.
I applied only parts of the previous patch because there were some problems with column bodies and row indexes. I will rerun unit tests for the new patch and judge if I can commit it. Thanks.
Hide
Ivan Markov
added a comment -
Hi James,
I took a brief look your patch. My comments inline (enclosed in []'s).
1) our backend is a mainframe that feeds us data in sets - you cannot know the full record size without first reading all the sets, which I don't want to have to do.
[Ivan: OK. But as far as I remember, the DT code needed to know the count of all records in the full list in order to render the pages' links at the top of the table. How do you overcome this?]
2) the size of each set is controlled by the backend, not DT. So, although DT might display 10 records per page, we are forced to get data back in 100-record sets. 1 data set can back 10 DT pages. This means each page-hit does NOT coincide with a DB-hit.
[Ivan: Point taken. although such caching scheme can be implemented in specific DataProvider as well.]
3) the "marker" for fetching the next data set is returned to us by the previous set - it is not sufficient just to know what page you are on. In order to get the "marker" for the 10th page, you must first traverse the previous 9.
[Ivan: Again, this could be implemented in the specific DataProvider.]
4) One of the databases we are using is MS SQL Server, which although it does have the "top" select attribute to get the first 100, it cannot for instance grab the middle 100. To do this we rely on sorting the data by specific columns, the specify a ">" where clause to remove the first X records, then use the top specifier to get the first Y records. This has the overall effect of getting the middle N records, but seriously limits our sorting capability.
[Ivan: Yes, doing paging with MSSQL is bulky. Still, there is a better scheme which works fine if your primary key is a single integer column. I can send it to you if you are interested.]
[Ivan: I still see my solution as the more generic approach. I mean, all optimizations of yours can be implemented as a specific DataProvider implementation, can't they? (Don't forget that the DataProvider can be a stateful object in the user session, so you can cache your 100 records for the next few page requests.)
The DataProvider thing is the result of my efforts to a) allow the DT code to push as many time/memory consuming operations as possible to the backend b) still allow these operations to be implemented in Java if the backend is weak and can't handle these - I would repeat for the n-th time that for this you just need a specific DataProvider implementation.
IMO representing the data as iterable list exposes too much semantics to the DT code and it is too easy to use operations that result in lots of CPU/Network usage.]
I took a brief look your patch. My comments inline (enclosed in []'s).
1) our backend is a mainframe that feeds us data in sets - you cannot know the full record size without first reading all the sets, which I don't want to have to do.
[Ivan: OK. But as far as I remember, the DT code needed to know the count of all records in the full list in order to render the pages' links at the top of the table. How do you overcome this?]
2) the size of each set is controlled by the backend, not DT. So, although DT might display 10 records per page, we are forced to get data back in 100-record sets. 1 data set can back 10 DT pages. This means each page-hit does NOT coincide with a DB-hit.
[Ivan: Point taken. although such caching scheme can be implemented in specific DataProvider as well.]
3) the "marker" for fetching the next data set is returned to us by the previous set - it is not sufficient just to know what page you are on. In order to get the "marker" for the 10th page, you must first traverse the previous 9.
[Ivan: Again, this could be implemented in the specific DataProvider.]
4) One of the databases we are using is MS SQL Server, which although it does have the "top" select attribute to get the first 100, it cannot for instance grab the middle 100. To do this we rely on sorting the data by specific columns, the specify a ">" where clause to remove the first X records, then use the top specifier to get the first Y records. This has the overall effect of getting the middle N records, but seriously limits our sorting capability.
[Ivan: Yes, doing paging with MSSQL is bulky. Still, there is a better scheme which works fine if your primary key is a single integer column. I can send it to you if you are interested.]
[Ivan: I still see my solution as the more generic approach. I mean, all optimizations of yours can be implemented as a specific DataProvider implementation, can't they? (Don't forget that the DataProvider can be a stateful object in the user session, so you can cache your 100 records for the next few page requests.)
The DataProvider thing is the result of my efforts to a) allow the DT code to push as many time/memory consuming operations as possible to the backend b) still allow these operations to be implemented in Java if the backend is weak and can't handle these - I would repeat for the n-th time that for this you just need a specific DataProvider implementation.
IMO representing the data as iterable list exposes too much semantics to the DT code and it is too easy to use operations that result in lots of CPU/Network usage.]
Show
Ivan Markov
added a comment - Hi James,
I took a brief look your patch. My comments inline (enclosed in []'s).
1) our backend is a mainframe that feeds us data in sets - you cannot know the full record size without first reading all the sets, which I don't want to have to do.
[Ivan: OK. But as far as I remember, the DT code needed to know the count of all records in the full list in order to render the pages' links at the top of the table. How do you overcome this?]
2) the size of each set is controlled by the backend, not DT. So, although DT might display 10 records per page, we are forced to get data back in 100-record sets. 1 data set can back 10 DT pages. This means each page-hit does NOT coincide with a DB-hit.
[Ivan: Point taken. although such caching scheme can be implemented in specific DataProvider as well.]
3) the "marker" for fetching the next data set is returned to us by the previous set - it is not sufficient just to know what page you are on. In order to get the "marker" for the 10th page, you must first traverse the previous 9.
[Ivan: Again, this could be implemented in the specific DataProvider.]
4) One of the databases we are using is MS SQL Server, which although it does have the "top" select attribute to get the first 100, it cannot for instance grab the middle 100. To do this we rely on sorting the data by specific columns, the specify a ">" where clause to remove the first X records, then use the top specifier to get the first Y records. This has the overall effect of getting the middle N records, but seriously limits our sorting capability.
[Ivan: Yes, doing paging with MSSQL is bulky. Still, there is a better scheme which works fine if your primary key is a single integer column. I can send it to you if you are interested.]
[Ivan: I still see my solution as the more generic approach. I mean, all optimizations of yours can be implemented as a specific DataProvider implementation, can't they? (Don't forget that the DataProvider can be a stateful object in the user session, so you can cache your 100 records for the next few page requests.)
The DataProvider thing is the result of my efforts to a) allow the DT code to push as many time/memory consuming operations as possible to the backend b) still allow these operations to be implemented in Java if the backend is weak and can't handle these - I would repeat for the n-th time that for this you just need a specific DataProvider implementation.
IMO representing the data as iterable list exposes too much semantics to the DT code and it is too easy to use operations that result in lots of CPU/Network usage.]
Hide
fabrizio giustina
added a comment -
We are talking about two different things here, I think you should open 2 separate reports for:
- refactoring of displaytag to use partial lists and to allow users to plug-in different implementations of "data providers" (original subject for this report, planned for 1.1)
- optimization which allows using a list without the need of iterating on each row (partially implemented, can be done for 1.0)
- refactoring of displaytag to use partial lists and to allow users to plug-in different implementations of "data providers" (original subject for this report, planned for 1.1)
- optimization which allows using a list without the need of iterating on each row (partially implemented, can be done for 1.0)
Show
fabrizio giustina
added a comment - We are talking about two different things here, I think you should open 2 separate reports for:
- refactoring of displaytag to use partial lists and to allow users to plug-in different implementations of "data providers" (original subject for this report, planned for 1.1)
- optimization which allows using a list without the need of iterating on each row (partially implemented, can be done for 1.0)
Hide
Bastian Bowe
added a comment -
Is there a version of dt_pdf_paging.diff against a newer snapshot. I would be very thankfull if one could post a diff against the trunk, because I need some features of rc2 together with you nice patch.
Show
Bastian Bowe
added a comment - Is there a version of dt_pdf_paging.diff against a newer snapshot. I would be very thankfull if one could post a diff against the trunk, because I need some features of rc2 together with you nice patch.
Hide
Bastian Bowe
added a comment -
Here is a patch that can be applied on top of dt_pdf_paging_java.zip. It simply solves the issues of DISPL-117 for dt_pdf_paging_java.zip. It does this by applying the changes in cvs made by fabrizio, that were caused by DISPL-117 and additionally adding the "excludeRequestParams" parameter to the table tag.
Show
Bastian Bowe
added a comment - Here is a patch that can be applied on top of dt_pdf_paging_java.zip. It simply solves the issues of DISPL-117 for dt_pdf_paging_java.zip. It does this by applying the changes in cvs made by fabrizio, that were caused by DISPL-117 and additionally adding the "excludeRequestParams" parameter to the table tag.
Hide
James Schopp
added a comment -
Ivan,
Regarding the point about showing the total list size:
* we have overridden the "messages" shown to the user, so instead of saying "Records 1-10 of 100", we say "Records 1-10. More Available", and the "Last" button says "More". Then, once we have finally reached the end (our lists have a flag that tell us this), we then switch back to the "normal" messages taht you would expect.
Regarding your comment "representing the data as iterable list exposes too much semantics to the DT":
* the truth is actually the opposite: DT has absolutely no knowledge that my lists are "lazy loading" the data - it only knows it has "a list"! On the contrary, adding "Data Providers" does mean modifying DT substantially. The reason that I require patches to DT is because of all the iterations DT makes over the entire list (causing all the data to be loaded everytime... the worst case scenario!). IF DT did not iterate so often over the entire list, then the solution would work perfectly (and fixing this is something that benefits EVERYONE, since DT really should iterate just once over minimal necessary records - no more, no less)
I imagine that the Data Provider strategy must have the same problem too, right? I mean, if DT asks for the 1000th record, you have to fetch it from the DB, so the multiple iterations means multiple DD calls.
IN ANY CASE: my "smart list" solution is *not* mutually exclusive to the Data Provider solution. Our environment uses the smart lists in other environments other than just web-based tables, so we solve the problem in those environments using this same technology. The Data Provider would be a perfect solution for us as well if we didn't have to support these other environments.
regards,
james
Regarding the point about showing the total list size:
* we have overridden the "messages" shown to the user, so instead of saying "Records 1-10 of 100", we say "Records 1-10. More Available", and the "Last" button says "More". Then, once we have finally reached the end (our lists have a flag that tell us this), we then switch back to the "normal" messages taht you would expect.
Regarding your comment "representing the data as iterable list exposes too much semantics to the DT":
* the truth is actually the opposite: DT has absolutely no knowledge that my lists are "lazy loading" the data - it only knows it has "a list"! On the contrary, adding "Data Providers" does mean modifying DT substantially. The reason that I require patches to DT is because of all the iterations DT makes over the entire list (causing all the data to be loaded everytime... the worst case scenario!). IF DT did not iterate so often over the entire list, then the solution would work perfectly (and fixing this is something that benefits EVERYONE, since DT really should iterate just once over minimal necessary records - no more, no less)
I imagine that the Data Provider strategy must have the same problem too, right? I mean, if DT asks for the 1000th record, you have to fetch it from the DB, so the multiple iterations means multiple DD calls.
IN ANY CASE: my "smart list" solution is *not* mutually exclusive to the Data Provider solution. Our environment uses the smart lists in other environments other than just web-based tables, so we solve the problem in those environments using this same technology. The Data Provider would be a perfect solution for us as well if we didn't have to support these other environments.
regards,
james
Show
James Schopp
added a comment - Ivan,
Regarding the point about showing the total list size:
* we have overridden the "messages" shown to the user, so instead of saying "Records 1-10 of 100", we say "Records 1-10. More Available", and the "Last" button says "More". Then, once we have finally reached the end (our lists have a flag that tell us this), we then switch back to the "normal" messages taht you would expect.
Regarding your comment "representing the data as iterable list exposes too much semantics to the DT":
* the truth is actually the opposite: DT has absolutely no knowledge that my lists are "lazy loading" the data - it only knows it has "a list"! On the contrary, adding "Data Providers" does mean modifying DT substantially. The reason that I require patches to DT is because of all the iterations DT makes over the entire list (causing all the data to be loaded everytime... the worst case scenario!). IF DT did not iterate so often over the entire list, then the solution would work perfectly (and fixing this is something that benefits EVERYONE, since DT really should iterate just once over minimal necessary records - no more, no less)
I imagine that the Data Provider strategy must have the same problem too, right? I mean, if DT asks for the 1000th record, you have to fetch it from the DB, so the multiple iterations means multiple DD calls.
IN ANY CASE: my "smart list" solution is *not* mutually exclusive to the Data Provider solution. Our environment uses the smart lists in other environments other than just web-based tables, so we solve the problem in those environments using this same technology. The Data Provider would be a perfect solution for us as well if we didn't have to support these other environments.
regards,
james
Hide
Dennie de Lange
added a comment -
Cross post from DISPL-134,
Sorry, I want this discussion to get active and this issue has more viewers.
Hello,
I am looking over the different issues regarding paging with large resultsets. There are many different solutions for it. I like to know which direction displaytag is going and if any work on it is being done currently. I couldn't find any pointers in the code or documentation.
I.m.h.o. it should be kept simple and configurable in the tag. I would be bad to ask the developer to implement a different list to support custom subselects, not all developers have access to the List. An attribute like virtualsize makes sence. Maybe we should close the other issues and leave one issue open to this issue. If any help is required I'll try to make some extra time.
Thanks in advance.
Greetz Dennie
Sorry, I want this discussion to get active and this issue has more viewers.
Hello,
I am looking over the different issues regarding paging with large resultsets. There are many different solutions for it. I like to know which direction displaytag is going and if any work on it is being done currently. I couldn't find any pointers in the code or documentation.
I.m.h.o. it should be kept simple and configurable in the tag. I would be bad to ask the developer to implement a different list to support custom subselects, not all developers have access to the List. An attribute like virtualsize makes sence. Maybe we should close the other issues and leave one issue open to this issue. If any help is required I'll try to make some extra time.
Thanks in advance.
Greetz Dennie
Show
Dennie de Lange
added a comment - Cross post from DISPL-134 ,
Sorry, I want this discussion to get active and this issue has more viewers.
Hello,
I am looking over the different issues regarding paging with large resultsets. There are many different solutions for it. I like to know which direction displaytag is going and if any work on it is being done currently. I couldn't find any pointers in the code or documentation.
I.m.h.o. it should be kept simple and configurable in the tag. I would be bad to ask the developer to implement a different list to support custom subselects, not all developers have access to the List. An attribute like virtualsize makes sence. Maybe we should close the other issues and leave one issue open to this issue. If any help is required I'll try to make some extra time.
Thanks in advance.
Greetz Dennie
Hide
Matthew Payne
added a comment -
You guys have like 5+ different issues that are vitually the same(paging big results) someone link them in jira.
Show
Matthew Payne
added a comment - You guys have like 5+ different issues that are vitually the same(paging big results) someone link them in jira.
Show
fabrizio giustina
added a comment - see DISPL-122 and DISPL-129