views:

285

answers:

3

I have a website that lets people view rows in a table (each row is a picture). There are more than 100,000 rows. You can view different subsets of the rows, and you can view them with different sort orders. While you are viewing one of the rows, you can click the "Next" or "Previous" buttons to go the next/previous row in the list.

How would you implement the "Next" and "Previous" features of the website?

More specifically, if you have an arbitrary query that returns a list of up to 100,000+ rows, and you know some information about the current row someone is viewing, how do you determine the NEXT row efficiently?

Here is the pseudo-code of the solution I came up with when the website was young, and it worked well when there were only 1000 rows, but now that there are 100,000 rows I think it is eating up too much memory.

int nextRowId(string query, int currentRowId)
{
    array allRowIds = mysql_query(query);  // Takes up a lot of memory!
    int currentIndex = (index of currentRowId in allRowIds);  // Takes time!
    return allRowIds[currentIndex+1];
}

While you are thinking about this problem, remember that the website can store more information about the current row than just its ID (for example, the position of the current row in the result set), and this information can be used as a hint to help determine the ID of the next row.

Edit: Sorry for not mentioning this earlier, but this isn't just a static website: rows can often be added to the list, and rows can be re-ordered in the list. (Much rarer, rows can be removed from the list.) I think that I should worry about that kind of thing, but maybe you can convince me otherwise.

A: 

USe the mysql limit clause. as in select * from tableA limit 0,100;

You parametereize the 0 and 100 naturally, store them in a form or whereever you need, so you'd know the offset to use when the user hits Next. That'll require you to rerun the query for every next/prev page you render.

nos
Thanks for the answer! Please see my comments for Machine's answer because they both apply to your answer as well.
David Grayson
+4  A: 

Have you tried applying the LIMIT-clause to the query?

From the MySQL manual

The LIMIT clause can be used to constrain the number of rows returned by the SELECT statement. LIMIT takes one or two numeric arguments, which must both be nonnegative integer constants (except when using prepared statements).

With two arguments, the first argument specifies the offset of the first row to return, and the second specifies the maximum number of rows to return

SELECT * FROM tbl LIMIT 5,10;  # Retrieve rows 6-15

With one argument, the value specifies the number of rows to return from the beginning of the result set:

SELECT * FROM tbl LIMIT 5;     # Retrieve first 5 rows
PatrikAkerstrand
Limit is really the only way to go when paging through a list on a website.
Dave W. Smith
He said 'efficient' - offset/limit is going to entail iterating and filtering through all the rows prior to the ones you want.
Nick Johnson
Yep, but considering what he's using now, it's a huge step up to let the DBMS do the work of filtering and only send the necessary amount of data back to the client. Anyway, got a better suggestion off the top of your head, give it a shot.
PatrikAkerstrand
I think I'm definitely going to need to use a "LIMIT" clause in the final solution, but what exactly would be a good algorithm for using it? Keep in mind that items can be added to the list while the user is viewing it, and items can get re-ordered (I think I should consider these possibilities, but you can try to convince me it's okay to ignore them). Sorry for not mentioning that originally.
David Grayson
I think kind of the obvious thing is to just store a hint about what position the picture was in the list, and then when you need to find the next one you can use LIMIT and OFFSET and try to find where that picture is now, but I was hoping someone here would have a better idea or a great way to implement that.
David Grayson
+1  A: 

Offset is a very expensive operation on large data sets, check out this presentation for more info about efficient paging in mySQL: http://www.scribd.com/doc/14683263/Efficient-Pagination-Using-MySQL

mynameiscoffey