<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	>
<channel>
	<title>Comments on: Using UNION to implement loose index scan in MySQL</title>
	<atom:link href="http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/</link>
	<description>Everything about MySQL Performance</description>
	<pubDate>Tue, 30 Sep 2008 23:54:20 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.5.1</generator>
		<item>
		<title>By: How to select the first/least/max row per group in SQL at Xaprb</title>
		<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-342483</link>
		<dc:creator>How to select the first/least/max row per group in SQL at Xaprb</dc:creator>
		<pubDate>Fri, 08 Aug 2008 15:39:39 +0000</pubDate>
		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-342483</guid>
		<description>[...] Peter Zaitsev has written in detail about this technique, so I won&#8217;t go into it too much more here. If it suits your purposes, it can be a very good solution. [...]</description>
		<content:encoded><![CDATA[<p>[...] Peter Zaitsev has written in detail about this technique, so I won&#8217;t go into it too much more here. If it suits your purposes, it can be a very good solution. [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: How adding another table to JOIN can improve performance ? &#124; MySQL Performance Blog</title>
		<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-338958</link>
		<dc:creator>How adding another table to JOIN can improve performance ? &#124; MySQL Performance Blog</dc:creator>
		<pubDate>Sat, 02 Aug 2008 05:10:59 +0000</pubDate>
		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-338958</guid>
		<description>[...] have described  couple of solutions to this problem - using IN list instead of range or UNION which however require [...]</description>
		<content:encoded><![CDATA[<p>[...] have described  couple of solutions to this problem - using IN list instead of range or UNION which however require [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: James Day</title>
		<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1829</link>
		<dc:creator>James Day</dc:creator>
		<pubDate>Wed, 16 Aug 2006 18:30:54 +0000</pubDate>
		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1829</guid>
		<description>Apachez, one of many areas where it's known that the optimizer can be improved. They are gradually being done, no particular schedule for when each one is done. Other than more slowly than we'd all like. :)

James Day
Support Engineer, MySQL AB</description>
		<content:encoded><![CDATA[<p>Apachez, one of many areas where it&#8217;s known that the optimizer can be improved. They are gradually being done, no particular schedule for when each one is done. Other than more slowly than we&#8217;d all like. <img src='http://www.mysqlperformanceblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>James Day<br />
Support Engineer, MySQL AB</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: MySQL Performance Blog &#187; MySQL: Followup on UNION for query optimization, Query profiling</title>
		<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1775</link>
		<dc:creator>MySQL Performance Blog &#187; MySQL: Followup on UNION for query optimization, Query profiling</dc:creator>
		<pubDate>Mon, 14 Aug 2006 20:46:32 +0000</pubDate>
		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1775</guid>
		<description>[...] Few days ago I wrote  an article about using UNION to implement loose index scan. [...]</description>
		<content:encoded><![CDATA[<p>[...] Few days ago I wrote  an article about using UNION to implement loose index scan. [...]</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Apachez</title>
		<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1768</link>
		<dc:creator>Apachez</dc:creator>
		<pubDate>Mon, 14 Aug 2006 18:32:29 +0000</pubDate>
		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1768</guid>
		<description>Is this a MySQL Optimizer bug (which we could expect to be fixed in near future) or is this "by design" for the next couple of years ?

I mean the UNION is a nice workaround but needs more code and logic where just writing a "WHERE col BETWEEN 19 AND 22" is so much easier :-)</description>
		<content:encoded><![CDATA[<p>Is this a MySQL Optimizer bug (which we could expect to be fixed in near future) or is this &#8220;by design&#8221; for the next couple of years ?</p>
<p>I mean the UNION is a nice workaround but needs more code and logic where just writing a &#8220;WHERE col BETWEEN 19 AND 22&#8243; is so much easier <img src='http://www.mysqlperformanceblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: peter</title>
		<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1724</link>
		<dc:creator>peter</dc:creator>
		<pubDate>Sun, 13 Aug 2006 15:52:08 +0000</pubDate>
		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1724</guid>
		<description>Yuan WANG,

If query with where clause "age=19 and zip in (...)" is executed what really is performed is sequence of lookups 
age=19 and zip=const.   Key length=4 is missleading in this case. It seems to be EXPLAIN bug in this case. 

For query with "age between 19 and 22 and zip in (...)"  what you have described is happening -  index range lookup is performend on age condition and zip condition only checked after row is read. 

You can use FLUSH STATUS;  &lt;run query&gt;  SHOW STATUS;   and check Handler_XXX stats to see how query execution was performed.</description>
		<content:encoded><![CDATA[<p>Yuan WANG,</p>
<p>If query with where clause &#8220;age=19 and zip in (&#8230;)&#8221; is executed what really is performed is sequence of lookups<br />
age=19 and zip=const.   Key length=4 is missleading in this case. It seems to be EXPLAIN bug in this case. </p>
<p>For query with &#8220;age between 19 and 22 and zip in (&#8230;)&#8221;  what you have described is happening -  index range lookup is performend on age condition and zip condition only checked after row is read. </p>
<p>You can use FLUSH STATUS;  <run query>  SHOW STATUS;   and check Handler_XXX stats to see how query execution was performed.</run></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Yuan WANG</title>
		<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1695</link>
		<dc:creator>Yuan WANG</dc:creator>
		<pubDate>Sat, 12 Aug 2006 12:28:04 +0000</pubDate>
		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1695</guid>
		<description>Hi peter:

Sorry to disturb you but I don't quite understand the big performance difference between the "age=19" query and the "age BETWEEN 18 AND 22 AND" query. According to the output of the EXPLAINs, I think the process of executing the "age=19" query is:
1. Perform an index scan of KEY(age, zip), with scankey "age=19". For key_len is 4, the condition on zip is useless in this step;
2. For each rows returned by the index scan above, retreive that row from the table and test where it's zip is in (12345, 12346, 12347)
And I think the process of executing the "age BETWEEN 18 AND 22 AND" query is:
1. Perform an index range scan of KEY(age, zip), start with "age=18" and end with "age=22". For key_len is 4, the condition on zip is useless in this step;
2. For each rows returned by the index scan above, retreive that row from the table and test where it's zip is in (12345, 12346, 12347)
So the main difference should be the first step. If the data has a uniform distribution, number of rows checked and returned by the first step of the "age=19" query should be about 1/5 of the "age BETWEEN 18 AND 22 AND" qeury, so would be the total cost.

However, the difference of the real cost is much more tremendous. So chould you be so kind to give some more words about the reason of the performance difference?</description>
		<content:encoded><![CDATA[<p>Hi peter:</p>
<p>Sorry to disturb you but I don&#8217;t quite understand the big performance difference between the &#8220;age=19&#8243; query and the &#8220;age BETWEEN 18 AND 22 AND&#8221; query. According to the output of the EXPLAINs, I think the process of executing the &#8220;age=19&#8243; query is:<br />
1. Perform an index scan of KEY(age, zip), with scankey &#8220;age=19&#8243;. For key_len is 4, the condition on zip is useless in this step;<br />
2. For each rows returned by the index scan above, retreive that row from the table and test where it&#8217;s zip is in (12345, 12346, 12347)<br />
And I think the process of executing the &#8220;age BETWEEN 18 AND 22 AND&#8221; query is:<br />
1. Perform an index range scan of KEY(age, zip), start with &#8220;age=18&#8243; and end with &#8220;age=22&#8243;. For key_len is 4, the condition on zip is useless in this step;<br />
2. For each rows returned by the index scan above, retreive that row from the table and test where it&#8217;s zip is in (12345, 12346, 12347)<br />
So the main difference should be the first step. If the data has a uniform distribution, number of rows checked and returned by the first step of the &#8220;age=19&#8243; query should be about 1/5 of the &#8220;age BETWEEN 18 AND 22 AND&#8221; qeury, so would be the total cost.</p>
<p>However, the difference of the real cost is much more tremendous. So chould you be so kind to give some more words about the reason of the performance difference?</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: peter</title>
		<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1687</link>
		<dc:creator>peter</dc:creator>
		<pubDate>Fri, 11 Aug 2006 21:15:02 +0000</pubDate>
		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1687</guid>
		<description>Dmitry, 

This is not the case where index merge can apply:


mysql&gt; explain SELECT  SQL_NO_CACHE name FROM people WHERE age BETWEEN 18 AND 22 AND zip IN (12345,12346, 12347);
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
&#124; id &#124; select_type &#124; table  &#124; type  &#124; possible_keys &#124; key  &#124; key_len &#124; ref  &#124; rows &#124; Extra       &#124;
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
&#124;  1 &#124; SIMPLE      &#124; people &#124; range &#124; age,zip       &#124; zip  &#124; 3       &#124; NULL &#124;   19 &#124; Using where &#124;
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.00 sec)


As you see it can use only one of the indexes it selects to use zip as it is more selective;  
As corelation between indexes is not known it is hard to tell what will be faster to use one of indexes only or
to intersect row pointers from both indexes.

If you would need OR  in this case Index merge would apply. 


mysql&gt; explain SELECT  SQL_NO_CACHE name FROM people WHERE age BETWEEN 18 AND 22 OR zip IN (12345,12346, 12347);
+----+-------------+--------+-------------+---------------+---------+---------+------+-------+----------------------------------------+
&#124; id &#124; select_type &#124; table  &#124; type        &#124; possible_keys &#124; key     &#124; key_len &#124; ref  &#124; rows  &#124; Extra                                  &#124;
+----+-------------+--------+-------------+---------------+---------+---------+------+-------+----------------------------------------+
&#124;  1 &#124; SIMPLE      &#124; people &#124; index_merge &#124; age,zip       &#124; age,zip &#124; 1,3     &#124; NULL &#124; 38821 &#124; Using sort_union(age,zip); Using where &#124;
+----+-------------+--------+-------------+---------------+---------+---------+------+-------+----------------------------------------+
1 row in set (0.00 sec)</description>
		<content:encoded><![CDATA[<p>Dmitry, </p>
<p>This is not the case where index merge can apply:</p>
<p>mysql> explain SELECT  SQL_NO_CACHE name FROM people WHERE age BETWEEN 18 AND 22 AND zip IN (12345,12346, 12347);<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;-+<br />
| id | select_type | table  | type  | possible_keys | key  | key_len | ref  | rows | Extra       |<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;-+<br />
|  1 | SIMPLE      | people | range | age,zip       | zip  | 3       | NULL |   19 | Using where |<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;-+<br />
1 row in set (0.00 sec)</p>
<p>As you see it can use only one of the indexes it selects to use zip as it is more selective;<br />
As corelation between indexes is not known it is hard to tell what will be faster to use one of indexes only or<br />
to intersect row pointers from both indexes.</p>
<p>If you would need OR  in this case Index merge would apply. </p>
<p>mysql> explain SELECT  SQL_NO_CACHE name FROM people WHERE age BETWEEN 18 AND 22 OR zip IN (12345,12346, 12347);<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
| id | select_type | table  | type        | possible_keys | key     | key_len | ref  | rows  | Extra                                  |<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
|  1 | SIMPLE      | people | index_merge | age,zip       | age,zip | 1,3     | NULL | 38821 | Using sort_union(age,zip); Using where |<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
1 row in set (0.00 sec)</p>
]]></content:encoded>
	</item>
	<item>
		<title>By: peter</title>
		<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1684</link>
		<dc:creator>peter</dc:creator>
		<pubDate>Fri, 11 Aug 2006 21:05:19 +0000</pubDate>
		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1684</guid>
		<description>Michael, 

You're right. This problem seems to be partially fixed and IN works for this case as well as union


mysql&gt; explain SELECT name FROM people WHERE age in (18,19,20,21,22) AND zip IN (12345,12346, 12347);
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
&#124; id &#124; select_type &#124; table  &#124; type  &#124; possible_keys &#124; key  &#124; key_len &#124; ref  &#124; rows &#124; Extra       &#124;
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
&#124;  1 &#124; SIMPLE      &#124; people &#124; range &#124; age           &#124; age  &#124; 4       &#124; NULL &#124;   16 &#124; Using where &#124;
+----+-------------+--------+-------+---------------+------+---------+------+------+-------------+
1 row in set (0.16 sec)


mysql&gt; SELECT name FROM people WHERE age in (18,19,20,21,22) AND zip IN (12345,12346, 12347);
+----------------------------------+
&#124; name                             &#124;
+----------------------------------+
&#124; ed4481336eb9adca222fd404fa15658e &#124;
&#124; 888ba838661aff00bbbce114a2a22423 &#124;
+----------------------------------+
2 rows in set (0.05 sec)

I actually ment a bit different case but I thought I should simplify it which turned to be not the best way around. 
I'll post one more post in couple of days to show where union will be the only this which can help you :)</description>
		<content:encoded><![CDATA[<p>Michael, </p>
<p>You&#8217;re right. This problem seems to be partially fixed and IN works for this case as well as union</p>
<p>mysql> explain SELECT name FROM people WHERE age in (18,19,20,21,22) AND zip IN (12345,12346, 12347);<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;-+<br />
| id | select_type | table  | type  | possible_keys | key  | key_len | ref  | rows | Extra       |<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;-+<br />
|  1 | SIMPLE      | people | range | age           | age  | 4       | NULL |   16 | Using where |<br />
+&#8212;-+&#8212;&#8212;&#8212;&#8212;-+&#8212;&#8212;&#8211;+&#8212;&#8212;-+&#8212;&#8212;&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;+&#8212;&#8212;&#8212;&#8212;-+<br />
1 row in set (0.16 sec)</p>
<p>mysql> SELECT name FROM people WHERE age in (18,19,20,21,22) AND zip IN (12345,12346, 12347);<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
| name                             |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
| ed4481336eb9adca222fd404fa15658e |<br />
| 888ba838661aff00bbbce114a2a22423 |<br />
+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;-+<br />
2 rows in set (0.05 sec)</p>
<p>I actually ment a bit different case but I thought I should simplify it which turned to be not the best way around.<br />
I&#8217;ll post one more post in couple of days to show where union will be the only this which can help you <img src='http://www.mysqlperformanceblog.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /></p>
]]></content:encoded>
	</item>
	<item>
		<title>By: Dmitry</title>
		<link>http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1683</link>
		<dc:creator>Dmitry</dc:creator>
		<pubDate>Fri, 11 Aug 2006 20:01:37 +0000</pubDate>
		<guid isPermaLink="false">http://www.mysqlperformanceblog.com/2006/08/10/using-union-to-implement-loose-index-scan-to-mysql/#comment-1683</guid>
		<description>Talking about MySQL 5 - what if you had two indices on `age` and `zip` separately, how would it look like in explain?</description>
		<content:encoded><![CDATA[<p>Talking about MySQL 5 - what if you had two indices on `age` and `zip` separately, how would it look like in explain?</p>
]]></content:encoded>
	</item>
</channel>
</rss>
