<?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>Blogrescue.com</title>
	<atom:link href="http://blogrescue.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://blogrescue.com</link>
	<description>Technical Know-How in Human Terms</description>
	<lastBuildDate>Fri, 11 May 2012 22:30:03 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3.2</generator>
		<item>
		<title>Nestwork Launch</title>
		<link>http://blogrescue.com/2012/05/nestwork-launch/</link>
		<comments>http://blogrescue.com/2012/05/nestwork-launch/#comments</comments>
		<pubDate>Fri, 11 May 2012 22:28:55 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://blogrescue.com/?p=512</guid>
		<description><![CDATA[Nestwork.net is a service that backs up your Twitter Network of Friends, Followers and Lists. It also tracks changes which might help you better cope with the infamous Twitter Unfollow Bug. If you are interested, follow the link below: The site was actually live and functional last week, but today saw some graphic and interface [...]]]></description>
			<content:encoded><![CDATA[<p><a href='http://nestwork.net'>Nestwork.net</a> is a service that backs up your Twitter Network of Friends, Followers and Lists.  It also tracks changes which might help you better cope with the infamous Twitter Unfollow Bug.  If you are interested, follow the link below: </p>
<p><center><a href="http://nestwork.net"><img src="http://blogrescue.com/wp-content/uploads/2012/05/BannerLogoUpdate-1.png" alt="" title="BannerLogoUpdate (1)" width="365" height="75" class="alignright size-full wp-image-513" /></a></center></p>
<p>The site was actually live and functional last week, but today saw some graphic and interface updates that make things quite a bit more presentable!  </p>
]]></content:encoded>
			<wfw:commentRss>http://blogrescue.com/2012/05/nestwork-launch/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitter API Made Easy</title>
		<link>http://blogrescue.com/2012/05/twitter-api-made-easy/</link>
		<comments>http://blogrescue.com/2012/05/twitter-api-made-easy/#comments</comments>
		<pubDate>Thu, 10 May 2012 16:04:23 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Twitter]]></category>

		<guid isPermaLink="false">http://blogrescue.com/?p=498</guid>
		<description><![CDATA[While working on NestWork, I needed to send Twitter API requests that were authenticated for different users. This excellent post got me about 95% of the way there. The two missing pieces were: Ability to send parameters with requests Ability to send multiple requests The first was actually fairly simple to fix – once you [...]]]></description>
			<content:encoded><![CDATA[<p>While working on <a href=’http://nestwork.net’>NestWork</a>, I needed to send Twitter API requests that were authenticated for different users.  <a href=’ http://erisds.co.uk/code/twitter-oauth-simple-curl-requests-for-your-own-data’> This excellent post</a> got me about 95% of the way there.  The two missing pieces were:</p>
<ol>
<li>Ability to send parameters with requests</li>
<li>Ability to send multiple requests</li>
</ol>
<p>The first was actually fairly simple to fix – once you understand that not only do the auth parameters go into generating the request signature, but the request parameters also must be part of the signature or the request will fail.  Took a little trial and error to figure this out and the code change was very simple to put into effect.</p>
<p>The second item was tricky, since I could send one request and it would work but any subsequent requests always failed.  For a few hours, I assumed that the second request failed and I was using the API wrong.  Once I only sent that request, it worked fine – which led to the revelation that my class used the same $oauth array for signature calculation and request generation.  That was ok, but after the first request, the signature had been added to the array.  Any subsequent request would then include the old signature value in the new signature generation and then replace the old value in the array.  This meant that the signature would be invalid.  Once I deduced the nature of the problem, solving it was simple.</p>
<p>I redeveloped the code into a php class to make it modular and easier to work with which I’m happy to share.</p>
<p>The class starts by defining the key variables (such as the application tokens) as well as the constructor &#8211; which accepts the user tokens we are making requests on behalf of. </p>
<pre>
class tapi {
  var $consumer_key = ‘CONSUMER_KEY_HERE;
  var $consumer_secret = ‘CONSUMER_SECRET_HERE’;
  var $access_token;
  var $access_secret;
  var $oauth;

  function tapi($token, $secret) {
    $this->access_token = $token;
    $this->access_secret = $secret;

    $this->oauth = array(
      'oauth_consumer_key' => $this->consumer_key,
      'oauth_token' => $this->access_token,
      'oauth_signature_method' => 'HMAC-SHA1',
      'oauth_timestamp' => time(),
      'oauth_nonce' => time(),
      'oauth_version' => '1.0'
    );
  }
</pre>
<p>This is followed by two key methods from ErisDS which do a nice job building the request url and the authorization header:</p>
<pre>
  function build_url($request, $params) {
    $url = "http://api.twitter.com/1/$request";
    if(count($params)) {
      $query = array();
      foreach($params as $key=>$value)
        $query[] = "$key=" . rawurlencode($value);

      $url .= '?' . implode('&#038;', $query);
    }

    return $url;
  }

  function build_authorization_header()
  {
    $r = 'Authorization: OAuth ';
    $values = array();
    foreach($this->oauth as $key=>$value)
        $values[] = "$key=\"" . rawurlencode($value) . "\"";

    $r .= implode(', ', $values);
    return $r;
  }
</pre>
<p>Then I’ve added a convenience method to build the base string that is used when generating the signature.  And I’ve created a build signature method from the ErisDS code.  The difference is that I’m also allowing parameters to be included in the request.  Also note that the “oauth_signature” element from the parameter array is ignored when building the base string.  This is the fix for the subsequent request failure issue I mentioned above.</p>
<pre>
  function build_base_string($request, $method, $params)
  {
    $r = array();
    ksort($params);
    foreach($params as $key=>$value){
      if($key == "oauth_signature") continue;
      $r[] = "$key=" . rawurlencode($value);
    }

    return $method."&#038;".rawurlencode("http://api.twitter.com/1/$request").'&#038;'.
      rawurlencode(implode('&#038;', $r)); //return complete base string
  }

  function build_signature($request, $params) {
    $all_params = array_merge($params, $this->oauth);
    $base_info = $this->build_base_string($request, 'GET', $all_params);

    $composite_key = rawurlencode($this->consumer_secret) . '&#038;' .
      rawurlencode($this->access_secret);
    $oauth_signature = base64_encode(hash_hmac('sha1', $base_info,
      $composite_key, true));
    $this->oauth['oauth_signature'] = $oauth_signature;
  }
</pre>
<p>The most important method is send_request which takes the request and parameters and builds the url, generates the signature, sends the request and returns the result.</p>
<pre>
  function send_request($request, $params) {
    $url = $this->build_url($request, $params);
    $this->build_signature($request, $params);

    $header = array($this->build_authorization_header(), 'Expect:');
    $options = array( CURLOPT_HTTPHEADER => $header,
                  CURLOPT_HEADER => false,
                  CURLOPT_URL => $url,
                  CURLOPT_RETURNTRANSFER => true,
                  CURLOPT_SSL_VERIFYPEER => false);
    $feed = curl_init();
    curl_setopt_array($feed, $options);
    $json = curl_exec($feed);
    curl_close($feed);

    $twitter_data = json_decode($json);
    return $twitter_data;
  }
</pre>
<p>The class is essentially complete but I decided that I wanted helper methods for the different requests so I can default parameters and make the request as dummy proof as possible.  Here are a few examples:</p>
<pre>

  function verify_credentials() {
    $request = "account/verify_credentials.json";
    $params = array();

    $result = $this->send_request($request, $params);
    return($result);
  }

  function user_lookup($list) {
    $request = "users/lookup.json";
    $params = array('user_id'=>$list);
    // where list is a comma delimited list of twitter ids – up to 100

    $result = $this->send_request($request, $params);
    return($result);
  }
</pre>
<p>The entire class is available for download here: <a href='http://blogrescue.com/downloads/tapi.zip'>tapi.zip</a>.  Hope someone else finds it useful.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogrescue.com/2012/05/twitter-api-made-easy/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitter Backup Service</title>
		<link>http://blogrescue.com/2012/04/twitter-backup-service/</link>
		<comments>http://blogrescue.com/2012/04/twitter-backup-service/#comments</comments>
		<pubDate>Mon, 30 Apr 2012 15:56:01 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Twitter Backup]]></category>

		<guid isPermaLink="false">http://blogrescue.com/?p=492</guid>
		<description><![CDATA[With the recent suspension of conservative Twitter accounts (seemingly based entirely on mass abuse reports by parties that don&#8217;t share the same worldview as those being blocked), an Instapundit reader came up with a great idea: Business plan! Escrow accounts for your Twitter followers. When your account gets suspended, and they blink, and reinstate you, [...]]]></description>
			<content:encoded><![CDATA[<p>With the recent suspension of conservative Twitter accounts (seemingly based entirely on mass abuse reports by parties that don&#8217;t share the same worldview as those being blocked), an Instapundit reader came up with a great idea: </p>
<blockquote><p>
<a href='http://pjmedia.com/instapundit/141900/'>Business plan! Escrow accounts for your Twitter followers. When your account gets suspended, and they blink, and reinstate you, it auto-adds your followers back.</a>.
</p></blockquote>
<p>I&#8217;ve been asked to develop this exact solution for someone who fears they might be FABanned (Fake Abuse Banned&#8230;pretty weak, but it&#8217;s Monday and the coffee hasn&#8217;t taken effect yet).  If others are interested, I can offer it as an affordable service.  </p>
<p>The way it will work (at least in my initial design) is it will use a read-only app to grab an account&#8217;s followers and friends and then zip them up in two formats and email them to the user at some interval&#8230;probably once a day.  There will be a machine readable format and a human readable version.  With the machine readable, it would be possible to automatically re-update the friends list using a app with write permissions.  I&#8217;m not sure if we can add followers back, but it might be possible to automatically tweet them to let them know that they are no longer following you.</p>
<p>If that sounds interesting to you, email me or post a comment on this post.</p>
<p>Ed</p>
<p><b>UPDATE:</b> I&#8217;ve got the service up and running now at <a href='http://nestwork.net'>Nestwork.net</a>.  Site development has been put on hold until I could get the backup functionality in place, so it isn&#8217;t a pretty place but the backups work!</p>
]]></content:encoded>
			<wfw:commentRss>http://blogrescue.com/2012/04/twitter-backup-service/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Happy Tax Day</title>
		<link>http://blogrescue.com/2012/04/happy-tax-day/</link>
		<comments>http://blogrescue.com/2012/04/happy-tax-day/#comments</comments>
		<pubDate>Tue, 17 Apr 2012 16:47:42 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[Technology]]></category>

		<guid isPermaLink="false">http://blogrescue.com/?p=485</guid>
		<description><![CDATA[(Or unhappy, if you owe much money.) It might make you feel better to know that you are not alone! Even at 240 miles above the surface of the earth, it is still tax day outside the earth&#8217;s atmosphere&#8230;at least for a few Astronauts. No that didn&#8217;t make me feel better either.]]></description>
			<content:encoded><![CDATA[<div style='float:right;'><a href="http://blogrescue.com/wp-content/uploads/2012/04/file9901241727462.jpg"><img src="http://blogrescue.com/wp-content/uploads/2012/04/file9901241727462-300x300.jpg" alt="" title="file9901241727462" width="150" height="150" class="alignright size-medium wp-image-487" /></a></div>
<p>(Or unhappy, if you owe much money.)  </p>
<p>It might make you feel better to know that you are not alone!  Even at 240 miles above the surface of the earth, it is still tax day <a href="http://www.space.com/15301-astronauts-pay-taxes-space-station.html">outside the earth&#8217;s atmosphere</a>&#8230;at least for a few Astronauts.</p>
<p>No that didn&#8217;t make me feel better either.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogrescue.com/2012/04/happy-tax-day/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Twitchy iPhone App Released</title>
		<link>http://blogrescue.com/2012/04/twitchy-iphone-app-released/</link>
		<comments>http://blogrescue.com/2012/04/twitchy-iphone-app-released/#comments</comments>
		<pubDate>Fri, 13 Apr 2012 14:46:18 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[iOS]]></category>

		<guid isPermaLink="false">http://blogrescue.com/?p=480</guid>
		<description><![CDATA[Anyone who has submitted mobile apps to the Apple App Store, knows that it can be a nerve wracking experience. Too much of the last 3 weeks has been spent preparing, submitting, reworking and biting fingernails through the process. Tremendous relief came yesterday when the app was finally approved. (If you are interested, you can [...]]]></description>
			<content:encoded><![CDATA[<div style='float:right;'><img src="http://blogrescue.com/wp-content/uploads/2012/04/Twitchy_apple512-300x300.png" alt="" title="Twitchy_apple512" width="150" height="150" class="alignright size-medium wp-image-481" /></div>
<p>Anyone who has submitted mobile apps to the Apple App Store, knows that it can be a nerve wracking experience.  Too much of the last 3 weeks has been spent preparing, submitting, reworking and biting fingernails through the process.  Tremendous relief came yesterday when the app was finally approved. (If you are interested, you can get it <a href='http://itunes.apple.com/us/app/twitchy/id514054612'>here</a>!)</p>
<p>One more app left to develop for Twitchy&#8230;so I&#8217;d better get back to that.<a href="http://blogrescue.com/wp-content/uploads/2012/04/Twitchy_apple512.png"></a></p>
]]></content:encoded>
			<wfw:commentRss>http://blogrescue.com/2012/04/twitchy-iphone-app-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Briefly Unavailable for Scheduled Maintenance&#8230;</title>
		<link>http://blogrescue.com/2012/04/briefly-unavailable-for-scheduled-maintenance/</link>
		<comments>http://blogrescue.com/2012/04/briefly-unavailable-for-scheduled-maintenance/#comments</comments>
		<pubDate>Sat, 07 Apr 2012 21:49:33 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[Locked Site]]></category>
		<category><![CDATA[Update]]></category>

		<guid isPermaLink="false">http://blogrescue.com/?p=473</guid>
		<description><![CDATA[So what causes a WordPress blog to start saying &#8220;Briefly Unavailable for Scheduled Maintenance&#8230;Check back in a minute&#8221; and how do you fix it? The cause is this: When you auto update either WordPress or plugins, WordPress creates a temporary file in the WordPress root so users can&#8217;t access the site for a few minutes [...]]]></description>
			<content:encoded><![CDATA[<p>So what causes a WordPress blog to start saying &#8220;Briefly Unavailable for Scheduled Maintenance&#8230;Check back in a minute&#8221; and how do you fix it?</p>
<p><span style="text-decoration: underline;">The cause is this:</span> When you auto update either WordPress or plugins, WordPress creates a temporary file in the WordPress root so users can&#8217;t access the site for a few minutes while the update is performed. Pretty good idea, but if the update fails or for some reason the file is never removed, then both the site and the WordPress backend are not accessible to anyone.</p>
<p><span style="text-decoration: underline;">The fix is pretty simple:</span> remove the file and everything will be better again (although if you were doing a WordPress upgrade and it failed, your site may be in an unstable state or your database might still require conversion to the latest version).</p>
<p>The file that needs removing is called <code>.maintenance</code> (note the preceeding dot &#8211; it is important) and should reside in the WordPress root directory (where index.php and wp-content reside). Connect via ssh or ftp and remove this file and the site should be back online.</p>
<p>One other note &#8211; the preceeding dot on the filename makes it not show in a file listing (at least on Linux).  Use <code>ls -la</code> to show *ALL* files including those that start with a period.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogrescue.com/2012/04/briefly-unavailable-for-scheduled-maintenance/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Google Analytics &#8211; For Users</title>
		<link>http://blogrescue.com/2012/03/google-analytics-for-users/</link>
		<comments>http://blogrescue.com/2012/03/google-analytics-for-users/#comments</comments>
		<pubDate>Wed, 28 Mar 2012 23:25:37 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[Analytics]]></category>
		<category><![CDATA[email]]></category>

		<guid isPermaLink="false">http://blogrescue.com/?p=470</guid>
		<description><![CDATA[Today, Google introduced Account Activity which gives statistics and insight on the Google services you use. This is an opt-in service, Today we’re introducing Account Activity, a new feature in your Google Account. If you sign up, each month we’ll send you a link to a password-protected report with insights into your signed-in use of [...]]]></description>
			<content:encoded><![CDATA[<p>Today, Google introduced <a href="http://googleblog.blogspot.com/2012/03/giving-you-more-insight-into-your.html">Account Activity</a> which gives statistics and insight on the Google services you use. This is an opt-in service,</p>
<blockquote><p>Today we’re introducing Account Activity, a new feature in your Google Account. If you sign up, each month we’ll send you a link to a password-protected report with insights into your signed-in use of Google services.</p></blockquote>
<p>First month, it doesn&#8217;t tell you much but I can see that a few months down the road, comparing months might be interesting.  My current activity is:</p>
<ul>
<li><b>Emails sent:</b> 1,864 (to 1523 contacts)</li>
<li><b>Emails received:</b> 1,136 (from 223 contacts)</li>
</ul>
<p>I guess that is only 62 emails a day, on average.  How do I ever get any work done?</p>
]]></content:encoded>
			<wfw:commentRss>http://blogrescue.com/2012/03/google-analytics-for-users/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Interesting Links</title>
		<link>http://blogrescue.com/2012/03/interesting-links/</link>
		<comments>http://blogrescue.com/2012/03/interesting-links/#comments</comments>
		<pubDate>Tue, 27 Mar 2012 19:06:57 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[Browsers]]></category>
		<category><![CDATA[CSS]]></category>
		<category><![CDATA[General]]></category>
		<category><![CDATA[Javascript]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[The Web]]></category>

		<guid isPermaLink="false">http://blogrescue.com/?p=465</guid>
		<description><![CDATA[&#8230;well, at least I found them interesting. Your mileage may vary. Typographer&#8217;s Glossary All you ever wanted to know about typography, and more. I really need to read through this in its entirety at some point. Using Modernizr&#8230; Modernizr is a javascript library that detects CSS and HTML5 functionality. Neat way to develop a page [...]]]></description>
			<content:encoded><![CDATA[<p>&#8230;well, at least I found them interesting. Your mileage may vary.</p>
<ul class='list'>
<li>
<a href='https://www.playtype.com/about/typefaces/glossary'>Typographer&#8217;s Glossary</a><br />
All you ever wanted to know about typography, and more.  I really need to read through this in its entirety at some point.
</li>
<li>
<a href='http://html5doctor.com/using-modernizr-to-detect-html5-features-and-provide-fallbacks/'>Using Modernizr&#8230;</a><br />
Modernizr is a javascript library that detects CSS and HTML5 functionality.  Neat way to develop a page that doesn&#8217;t waste resources on things that won&#8217;t show up anyways.
</li>
<li>
<a href='http://ie.microsoft.com/testdrive/Performance/AsyncScripts/Default.html'>HTML5 Async Scripts</a><br />
I need to test this and see which browsers this helps on, but if speeding up sites is this easy, that is a win for everyone.  (Or maybe I should have kept this a secret to make my skills in more demand&#8230;Meh &#8211; not my style.)
</li>
<li>
<a href='http://www.readwriteweb.com/archives/why_i_love_cowbirdcom.php'>How Cowbird Transforms Storytelling on the Web</a><br />
Never heard of cowbird before but they have a pretty cool presentation.
</li>
<li>
<a href='http://www.idownloadblog.com/2012/03/26/no-native-pull-to-refresh/'>No ‘pull-to-refresh’ in native iOS apps</a><br />
The pull-to-refresh function was patented by Tweetie, which was later purchased by Twitter.  Hope they don&#8217;t go after indie developers with big lawyers!
</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blogrescue.com/2012/03/interesting-links/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>New Android App Released</title>
		<link>http://blogrescue.com/2012/03/new-android-app-released/</link>
		<comments>http://blogrescue.com/2012/03/new-android-app-released/#comments</comments>
		<pubDate>Wed, 07 Mar 2012 17:03:07 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[Android]]></category>

		<guid isPermaLink="false">http://blogrescue.com/?p=459</guid>
		<description><![CDATA[Posting has been light mostly because I&#8217;ve been heads down on a few new apps for a new site that just launched today. Twitchy is a Twitter aggregation site with actual humans doing the aggregation. The site works great, which I unfortunately cannot take any credit for. What I can take credit for is the [...]]]></description>
			<content:encoded><![CDATA[<div style='float:right;'><img src='http://blogrescue.com/wp-content/uploads/2012/03/twitchylaunch.png' /></div>
<p>Posting has been light mostly because I&#8217;ve been heads down on a few new apps for a new site that just launched today. </p>
<p><a href='http://twitchy.com'>Twitchy</a> is a Twitter aggregation site with actual humans doing the aggregation.  The site works great, which I unfortunately cannot take any credit for.  </p>
<p>What I can take credit for is the new android app available here: <a href='https://play.google.com/store/apps/details?id=com.twitchy.twitchyandroid&#038;feature=search_result#?t=W251bGwsMSwyLDEsImNvbS50d2l0Y2h5LnR3aXRjaHlhbmRyb2lkIl0.'>Twitchy Android</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blogrescue.com/2012/03/new-android-app-released/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>The value of Indexes (Mysql)</title>
		<link>http://blogrescue.com/2012/02/the-value-of-indexes-mysql/</link>
		<comments>http://blogrescue.com/2012/02/the-value-of-indexes-mysql/#comments</comments>
		<pubDate>Wed, 15 Feb 2012 05:26:34 +0000</pubDate>
		<dc:creator>Ed</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[indexes]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[optimization]]></category>
		<category><![CDATA[queries]]></category>

		<guid isPermaLink="false">http://blogrescue.com/?p=440</guid>
		<description><![CDATA[If you write any kind of code that uses databases , please spend a few minutes learning how indexes work. They are very easy to understand and even easier to implement and they can save you (and possibly others) from some very real headaches. I had to deal with a server outage this morning and [...]]]></description>
			<content:encoded><![CDATA[<p>If you write any kind of code that uses databases , please spend a few minutes learning how indexes work.  They are very easy to understand and even easier to implement and they can save you (and possibly others) from some very real headaches.</p>
<p>I had to deal with a server outage this morning and the culprit was a few slow queries running multiple times per second on a site that I host.  The cause turned out to be a WordPress plugin that provides good functionality but did not use any indexes on its tables.  There is no doubt in my mind that a significant number of plugins are out there that suffer from the same inefficiencies.</p>
<p>Here is the mysql-slow log entry for one of the queries:</p>
<pre>
# Time: 120214 10:16:04
# User@Host: db_user[db_name] @ localhost []
# Query_time: 5.142186  Lock_time: 0.000077 Rows_sent: 1  Rows_examined: 145277
SELECT SUM('clicks') as 'clicks', SUM('impressions') as 'impressions' FROM 'wp_adrotate_stats_tracker' WHERE 'ad' = '591';
</pre>
<p>What this means is that this query that sums the number of ‘clicks’ from the stats_tracker table for ad ‘591’ is taking over 5 seconds to execute and examines more than 145 thousand rows in order to determine the result.  I was certain that ad number 591 didn’t have 145,000 rows attributed to it so the first thing I did was add a new index to the table:</p>
<pre>
CREATE INDEX ad_idx ON wp_adrotate_stats_tracker (ad);
</pre>
<p>That is how you do it from the command line; it is even easier in phpMyAdmin.  After that, I issued the same query with ‘Explain’ in front of it, and it revealed that the query now examine a mere 700 rows – 0.4% of the records examined sans index.</p>
<p>Here is another example:</p>
<pre>
# Time: 111007  9:01:19
# User@Host: db_user[db_name] @ localhost []
# Query_time: 8.488923  Lock_time: 0.000106 Rows_sent: 1  Rows_examined: 49715
SELECT COUNT(*) FROM 'wp_adrotate_tracker' WHERE 'ipaddress' = '66.249.72.14' AND 'stat' = 'i' AND 'timer' < '1317999371' AND '>bannerid' = '55' LIMIT 1;
</pre>
<p>Examining 49,000 rows seems a bit high and ip address seems pretty specific, so I tried adding another index:</p>
<pre>
CREATE INDEX ip_idx ON wp_adrotate_tracker (ipaddress);
</pre>
<p>Any guesses at the number of rows the query had to examine now?  The answer is 49714 less than without the index – one single row (or if you prefer percentages&#8230;the query now consults 99.998% fewer rows than without the index).</p>
<p>The best thing about indexes is that even if the developer fails to foresee and add them, the end user can add them manually and they still work. (That&#8217;s what I did!) </p>
<p>If you want to learn more about indexes, here are a couple of solid links with great information:</p>
<ul>
<li><a href='http://www.databasejournal.com/features/mysql/article.php/1382791/Optimizing-MySQL-Queries-and-Indexes.htm'>DatabaseJournal: Optimizing MySQL Queries and Indexes</a></li>
<li><a href='http://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html'>Mysql.com: Mysql Indexes</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blogrescue.com/2012/02/the-value-of-indexes-mysql/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>

