Karl Seguin

Sponsors

The Lounge

Wicked Cool Jobs

Advertisement

Images in this post missing? We recently lost them in a site migration. We're working to restore these as you read this. Should you need an image in an emergency, please contact us at imagehelp@codebetter.com
Paging Data - MySQL > Microsoft
A little while ago, Scott Guthrie talked about record paging in his post "Paging through lots of data efficiently (and in an Ajax way) with ASP.NET 2.0". The important part of the article doesn't have much to do with ASP.NET or Ajax, but rather the new ranking capabilities found in SQL Server 2005. If you've done data paging before, or just think about it for a second, that shouldn't be much of a surprise. Without question, "efficiently" paging through data has to happen directly on the database.

The alternative to paging data at the database is to page it in ASP.NET. The DataGrid and GridView controls make it easy to page data in ASP.NET, but there's a price to be paid - performance. I know a lot of people are put off by micro optimizations (which you should be), but in my experience, paging even a bit of data under moderate load can have significant performance implications. Instead of simply returning the 10 rows from the database, you need to return all of the rows and let ASP.NET figure our which are the right ones to display. If your data is wide (a lot of columns) or you have a lot of rows, your site will suffer significant performance issues.  You should only use the built-in paging when you know you have very few records - say under a thousand - oh, and make sure to optimize that viewstate!

Before SQL Server 2005 came out, paging was frustratingly difficult. Ideally you'd be able to rely on an auto-genarated id and simply pick all records where the ID is between 1-10, 11-20, 21-30...But that only works if you can guarantee that there are no holes in your IDs, which likely you can't. One solution, the one I prefer, is to create a temp table (or a table data type), that has an auto id in it. Something like:

DECLARE @records TABLE(RowId INT IDENTITY(1,1), TableId INT)

INSERT INTO @records
   SELECT ProductId
   FROM Products
   WHERE Price <= @MaxPrice
      AND Price >= @MinPrice
      AND Category = @CategoryId
   ORDER BY ProductId

--get the total number of matching products
SELECT COUNT(*) FROM @records

--get the data

SELECT p.ProductId, [Name], Price, ImageUrl
   FROM Products p INNER JOIN @records r ON p.ProductId = r.TableId
   WHERE p.RowId > 0 AND p.RowId < 11 --these would be passed in



Although just a sample, the above code shows how you can create a temp table and create a series of id's with no holes. The temp table is kept extremely narrow (2 small columns) and short (the filtering is applied upfront), and is joined back against the main table. It ends up working very well. But it's a serious pain in the ass - especially when you consider how basic this is.

Since the dawn of SQL Server, people have been going about banging their heads on the best way to do this, begging Microsoft to implement a good solution. Disappointed by SQL Server 7 and 2000, the team behind 2005 finally decided to help out. With the new ranking functions, we end up with:

WITH PagedProducts AS
   (
      SELECT ROW_NUMBER() OVER (ORDER BY ProductId) AS RowNumber, ProductId, [Name], Price, ImageUrl
      FROM Products
      WHERE Price <= @MaxPrice
         AND Price >= @MinPrice
         AND Category = @CategoryId

   )
SELECT ProductId, [Name], Price, ImageUrl
FROM PagedProducts
WHERE RowNumber BETWEEN 1 AND 10

It's a step in the right direction, but I consider the above code overly complicated for the common task we are trying to accomplish. Why did the SQL team decide not to implement the oft-begged for MySQL LIMIT keyword? Even if LIMIT simply abstracts away the above code, it's embarrassingly simple:

SELECT ProductId, [Name], Price, ImageUrl FROM Products LIMIT 1,10

The ranking functions are meant to do more than just paging and that's great if you want to do more than just paging. But I'm convinced that paging is so fundamentally necessary to most applications, it deserves it's own straightforward keyword.

If you need to page results, MySQL's LIMIT keyword continues to be more handy than anything the .NET or SQL teams have managed to do.


Posted Mon, Apr 17 2006 5:00 AM by karl

[Advertisement]

Comments

scottgu wrote re: Paging Data - MySQL &gt; Microsoft
on Tue, Apr 18 2006 12:10 AM
On the positive side, I just got confirmation that the new version of DLINQ that is coming out in a few weeks will have a friendly syntax for doing LIMIT based queries -- so the future looks bright. :-)

Hope this helps,

Scott
karl wrote re: Paging Data - MySQL &gt; Microsoft
on Tue, Apr 18 2006 8:15 AM
Thanks for the good news!
SCarpenter wrote re: Paging Data - MySQL &gt; Microsoft
on Tue, Apr 18 2006 12:36 PM
Just for completeness, you should have an ORDER BY clause in your first example when the rows are inserted into the table variable.  Otherwise, the rows could go into the table variable in a different order on a subsequent execution, giving you weird results.
karl wrote re: Paging Data - MySQL &gt; Microsoft
on Tue, Apr 18 2006 12:51 PM
Thanks Sean...done :)
Karl Seguin [MVP] wrote SQL Server - No Arrays? No Problem!
on Mon, May 8 2006 10:41 AM
Use SQL Server's 2005 XML capabilities to pass in arrays of values instead of relying on multiple DB calls, UDFs or dynamic SQL.
Greg wrote re: Paging Data - MySQL &gt; Microsoft
on Wed, May 31 2006 7:19 PM
Is there a way in MySQL where you can pass the LIMIT parameters as variables?, because i'm using it in an stored procedure

CREATE PROCEDURE `getSociosComercialesPorCategoria`(IN limit INTEGER(11))
...
BEGIN
select * from table limit
Greg wrote re: Paging Data - MySQL &gt; Microsoft
on Wed, May 31 2006 7:20 PM
Is there a way in MySQL where you can pass the LIMIT parameters as variables?, because i'm using it in an stored procedure

CREATE PROCEDURE `getVal`(IN limit_return INTEGER(11))
...
BEGIN

  select * from table limit limit_return;

END;

But it throws me an error at the limit line.
Any suggestions??
karl wrote re: Paging Data - MySQL &gt; Microsoft
on Wed, May 31 2006 10:15 PM
According to MySql's doc:
"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 non-negative integer constants (except when using prepared statements)."

which would imply to me that you can't. I've used sprocs in mysql and I'm not particularly impressed...not sure I see any advantages yet, other than a physical layer separation.
Jay R. Wren - lazy dawg evarlast » Archive » Microsoftie praises MySQL? wrote Jay R. Wren - lazy dawg evarlast &raquo; Archive &raquo; Microsoftie praises MySQL?
on Thu, Nov 9 2006 3:21 PM
Raghu Rajbhandari wrote re: Paging Data - MySQL > Microsoft
on Wed, Sep 3 2008 8:43 AM

To use Limit clause in stored procedure in mysql we have to do a little trick. The statement in stored procedure that has the Limit clause has to be made into a prepared statement and the that prepared statement can be dynamically executed passing in the parameters for Limit clause's parameters.

The code below may explain :

DELIMITER $$

DROP PROCEDURE IF EXISTS `knowledgebase`.`test`$$

CREATE PROCEDURE `knowledgebase`.`test`(page int,maxrows int)

   /*LANGUAGE SQL

   | [NOT] DETERMINISTIC

   | { CONTAINS SQL | NO SQL | READS SQL DATA | MODIFIES SQL DATA }

   | SQL SECURITY { DEFINER | INVOKER }

   | COMMENT 'string'*/

   BEGIN

PREPARE stmt1 FROM 'select * from t_article LIMIT ?,?';

SET @a = page;

SET @b = maxrows;

EXECUTE stmt1 USING @a, @b;

   END$$

DELIMITER ;

sansriinfosys.fcc@gmail.com wrote re: Paging Data - MySQL > Microsoft
on Wed, Jan 28 2009 4:51 AM

MySQL LIMIT is simple to manage page navigation. In future i am expecting MS-SQL Server will also manage the same thing. I am using a table with 3.5 Lacks records in MySQL just it will getting the records with in 1.0ms when i use LIMIT 340000,100. We will see the same thing in future for MSSQL.

Twitter Trackbacks for Paging Data - MySQL > Microsoft - Karl Seguin - CodeBetter.Com - Stuff you need to Code Better! [codebetter.com] on Topsy.com wrote Twitter Trackbacks for Paging Data - MySQL &gt; Microsoft - Karl Seguin - CodeBetter.Com - Stuff you need to Code Better! [codebetter.com] on Topsy.com
on Wed, Aug 26 2009 5:24 PM

Pingback from  Twitter Trackbacks for                 Paging Data - MySQL > Microsoft - Karl Seguin - CodeBetter.Com - Stuff you need to Code Better!         [codebetter.com]        on Topsy.com

Devlicio.us