<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Eric Hynds &#187; MySQL</title>
	<atom:link href="http://www.erichynds.com/category/mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.erichynds.com</link>
	<description>Web Developer&#039;s Ramblings on JavaScript, jQuery, ColdFusion, MySQL, and other technologies.</description>
	<lastBuildDate>Mon, 02 Jan 2012 22:55:17 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Paginating large datasets with MySQL</title>
		<link>http://www.erichynds.com/coldfusion/paginating-large-datasets-with-mysql/</link>
		<comments>http://www.erichynds.com/coldfusion/paginating-large-datasets-with-mysql/#comments</comments>
		<pubDate>Thu, 27 Aug 2009 00:33:41 +0000</pubDate>
		<dc:creator>Eric Hynds</dc:creator>
				<category><![CDATA[ColdFusion]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://www.erichynds.com/blog/?p=27</guid>
		<description><![CDATA[Web developers typically choose one of two ways to paginate data: Select every row in one query and use server-side programming to handle the pagination and output. Use the LIMIT clause in the query to only select the amount of rows necessary for that page of results. Which ever you choose, each can have a [...]


Related posts:<ol><li><a href='http://www.erichynds.com/coldfusion/large-loops-out-of-memory/' rel='bookmark' title='Large loops = out of memory?'>Large loops = out of memory?</a></li>
</ol>]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.erichynds.com%2Fcoldfusion%2Fpaginating-large-datasets-with-mysql%2F"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.erichynds.com%2Fcoldfusion%2Fpaginating-large-datasets-with-mysql%2F&amp;source=erichynds&amp;style=normal&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p>Web developers typically choose one of two ways to paginate data:</p>
<ol>
<li>Select every row in one query and use server-side programming to handle the pagination and output.</li>
<li>Use the <code>LIMIT</code> clause in the query to only select the amount of rows necessary for that page of results.</li>
</ol>
<p>Which ever you choose, each can have a huge performance implication particularly when the data set is in the thousands of rows, or if the query to select the data is not optimized.</p>
<p>The performance hit in option #1 is obvious: you&#8217;re selecting ALL the rows when only a fraction of them are going to be displayed to the user at one time.  Depending on the situation and if the query can be cached, I suppose this is a fine option, but in my opinion, pagination is a job for your database layer.</p>
<p>In option #2 the query is only going to return XX number of rows out of the entire recordset.  We still need to know how many total rows exist in order to figure out how many pages there will be, and to display other meta data to users (showing records 1-100 of 4000, for example). Therefore, a second query still needs to be issued using a <code>COUNT()</code> statement, or the exact same query again without the <code>LIMIT</code> clause&#8230; not very efficient.</p>
<p>Although it doesn&#8217;t seem well known in the CF community, this scenario is the perfect fit for MySQL&#8217;s <code>SQL_CALC_FOUND_ROWS</code> and <code>FOUND_ROWS()</code>.  Basically, this statement and function used together gives us the ability to retrieve the total number of rows that would have been returned had the <code>LIMIT</code> statement not been used. Two queries still have to be issued, but this time without the performance hit.  Assuming our <code>start_record</code> and <code>records_per_page</code> variables are already set, it works like this:</p>

<div class="wp_syntax"><div class="code"><pre class="cfm" style="font-family:monospace;"><span style="color: #333333;"><span style="color: #0000FF;">&lt;</span><span style="color: #990000; font-weight: bold;">cftransaction</span><span style="color: #0000FF;">&gt;</span></span>
	<span style="color: #333333;"><span style="color: #0000FF;">&lt;</span><span style="color: #990000; font-weight: bold;">cfquery</span> <span style="color: #0000FF;">name</span><span style="color: #0000FF;">=</span><span style="color: #009900;">&quot;getData&quot;</span> <span style="color: #0000FF;">datasource</span><span style="color: #0000FF;">=</span><span style="color: #009900;">&quot;mydatasource&quot;</span><span style="color: #0000FF;">&gt;</span></span>
	SELECT SQL_CALC_FOUND_ROWS field1, field2, field3
	FROM ...
	WHERE ...
	LIMIT <span style="color: #0000FF;">#start_record#</span>, <span style="color: #0000FF;">#records_per_page#</span>
	<span style="color: #333333;"><span style="color: #0000FF;">&lt;/</span><span style="color: #990000; font-weight: bold;">cfquery</span><span style="color: #0000FF;">&gt;</span></span>
&nbsp;
	<span style="color: #333333;"><span style="color: #0000FF;">&lt;</span><span style="color: #990000; font-weight: bold;">cfquery</span> <span style="color: #0000FF;">name</span><span style="color: #0000FF;">=</span><span style="color: #009900;">&quot;getDataCount&quot;</span> <span style="color: #0000FF;">datasource</span><span style="color: #0000FF;">=</span><span style="color: #009900;">&quot;mydatasource&quot;</span><span style="color: #0000FF;">&gt;</span></span>
	SELECT FOUND_ROWS() AS totalrecords
	<span style="color: #333333;"><span style="color: #0000FF;">&lt;/</span><span style="color: #990000; font-weight: bold;">cfquery</span><span style="color: #0000FF;">&gt;</span></span>
<span style="color: #333333;"><span style="color: #0000FF;">&lt;/</span><span style="color: #990000; font-weight: bold;">cftransaction</span><span style="color: #0000FF;">&gt;</span></span></pre></div></div>

<p>The query getData retrieves only the rows we&#8217;re going to output, whereas query getDataCount retrieves the number of rows getData would have returned without the <code>LIMIT</code> restriction.  Note that you can issue a <code>SELECT FOUND_ROWS()</code> statement at any time whether you&#8217;re paginating or not, and it&#8217;ll return the recordcount for whatever the last <code>SELECT</code> was.  Therefore, in the example above, I&#8217;m wrapping both queries in a <code>cftransaction</code> tag so the <code>FOUND_ROWS()</code> will always reference the getData query.  If another query is issued at the same time by another user of your website, selecting <code>FOUND_ROWS()</code> will return the recordcount of that query, not from getData. Here&#8217;s a full example of how to build the pagination variables (untested!):</p>

<div class="wp_syntax"><div class="code"><pre class="cfm" style="font-family:monospace;"><span style="color: #808080; font-style: italic;">&lt;!--- the current page we're on ---&gt;</span>
<span style="color: #333333;"><span style="color: #0000FF;">&lt;</span><span style="color: #990000; font-weight: bold;">cfparam</span> <span style="color: #0000FF;">name</span><span style="color: #0000FF;">=</span><span style="color: #009900;">&quot;url.page&quot;</span> <span style="color: #0000FF;">default</span><span style="color: #0000FF;">=</span><span style="color: #009900;">&quot;1&quot;</span><span style="color: #0000FF;">&gt;</span></span>
&nbsp;
<span style="color: #808080; font-style: italic;">&lt;!--- number of records to display per page / retrieve in the query ---&gt;</span>
<span style="color: #333333;"><span style="color: #0000FF;">&lt;</span><span style="color: #990000; font-weight: bold;">cfset</span> records_per_page <span style="color: #0000FF;">=</span> <span style="color: #FF0000;">45</span><span style="color: #0000FF;">&gt;</span></span>
&nbsp;
<span style="color: #808080; font-style: italic;">&lt;!--- row to start on during our DB retrieve ---&gt;</span>
<span style="color: #333333;"><span style="color: #0000FF;">&lt;</span><span style="color: #990000; font-weight: bold;">cfset</span> start_record <span style="color: #0000FF;">=</span> url.page * records_per_page<span style="color: #0000FF;">&gt;</span></span>
&nbsp;
<span style="color: #808080; font-style: italic;">&lt;!--- get our data ---&gt;</span>
<span style="color: #333333;"><span style="color: #0000FF;">&lt;</span><span style="color: #990000; font-weight: bold;">cftransaction</span><span style="color: #0000FF;">&gt;</span></span>
	<span style="color: #333333;"><span style="color: #0000FF;">&lt;</span><span style="color: #990000; font-weight: bold;">cfquery</span> <span style="color: #0000FF;">name</span><span style="color: #0000FF;">=</span><span style="color: #009900;">&quot;getData&quot;</span> <span style="color: #0000FF;">datasource</span><span style="color: #0000FF;">=</span><span style="color: #009900;">&quot;mydatasource&quot;</span><span style="color: #0000FF;">&gt;</span></span>
	SELECT SQL_CALC_FOUND_ROWS field1, field2, field3
	FROM ...
	WHERE ...
	LIMIT <span style="color: #0000FF;">#start_record#</span>, <span style="color: #0000FF;">#records_per_page#</span>
	<span style="color: #333333;"><span style="color: #0000FF;">&lt;/</span><span style="color: #990000; font-weight: bold;">cfquery</span><span style="color: #0000FF;">&gt;</span></span>
&nbsp;
	<span style="color: #808080; font-style: italic;">&lt;!--- get total number of rows ---&gt;</span>
	<span style="color: #333333;"><span style="color: #0000FF;">&lt;</span><span style="color: #990000; font-weight: bold;">cfquery</span> <span style="color: #0000FF;">name</span><span style="color: #0000FF;">=</span><span style="color: #009900;">&quot;getDataCount&quot;</span> <span style="color: #0000FF;">datasource</span><span style="color: #0000FF;">=</span><span style="color: #009900;">&quot;mydatasource&quot;</span><span style="color: #0000FF;">&gt;</span></span>
	SELECT FOUND_ROWS() AS totalrecords
	<span style="color: #333333;"><span style="color: #0000FF;">&lt;/</span><span style="color: #990000; font-weight: bold;">cfquery</span><span style="color: #0000FF;">&gt;</span></span>
<span style="color: #333333;"><span style="color: #0000FF;">&lt;/</span><span style="color: #990000; font-weight: bold;">cftransaction</span><span style="color: #0000FF;">&gt;</span></span>
&nbsp;
<span style="color: #808080; font-style: italic;">&lt;!--- total number of pages ---&gt;</span>
<span style="color: #333333;"><span style="color: #0000FF;">&lt;</span><span style="color: #990000; font-weight: bold;">cfset</span> total_pages <span style="color: #0000FF;">=</span> <span style="color: #0000FF;">ceiling</span><span style="color: #0000FF;">&#40;</span>getDataCount.totalrecords <span style="color: #0000FF;">/</span> records_per_page<span style="color: #0000FF;">&#41;</span><span style="color: #0000FF;">&gt;</span></span></pre></div></div>

<p>In future versions of ColdFusion it would be nice to see some kind of implementation in the &#8220;result&#8221; attribute of CFQUERY.  If your result variable is &#8220;r&#8221;, for example, it would be cool to be able to reference <code>#r.found_rows#</code>, much like you can with <code>#r.generated_key#</code> during an INSERT.  I&#8217;m sure MSSQL and other DBMS&#8217;s have something similar, but I&#8217;ve only had to use this with MySQL.  Happy paginating!</p>


<p>Related posts:<ol><li><a href='http://www.erichynds.com/coldfusion/large-loops-out-of-memory/' rel='bookmark' title='Large loops = out of memory?'>Large loops = out of memory?</a></li>
</ol></p>]]></content:encoded>
			<wfw:commentRss>http://www.erichynds.com/coldfusion/paginating-large-datasets-with-mysql/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>

