<?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>code.openark.org &#187; SQL</title>
	<atom:link href="http://code.openark.org/blog/tag/sql/feed" rel="self" type="application/rss+xml" />
	<link>http://code.openark.org/blog</link>
	<description>Blog by Shlomi Noach</description>
	<lastBuildDate>Wed, 01 Feb 2012 08:19:12 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.3</generator>
		<item>
		<title>Syntax of the day: IS TRUE and IS FALSE</title>
		<link>http://code.openark.org/blog/mysql/syntax-of-the-day-is-true-and-is-false</link>
		<comments>http://code.openark.org/blog/mysql/syntax-of-the-day-is-true-and-is-false#comments</comments>
		<pubDate>Thu, 26 Jan 2012 04:09:23 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Syntax]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=4198</guid>
		<description><![CDATA[What makes for a true statement? We usually test statements using a WHERE clause: SELECT * FROM world.City WHERE Population &#62; 1000000 The "Population &#62; 1000000" statement makes for a boolean expression. Using WHERE is just one way of evaluating it. One can also test with IF(): SET @val := 7; SELECT IF(@val &#62; 2, [...]]]></description>
			<content:encoded><![CDATA[<p>What makes for a <em>true</em> statement?</p>
<p>We usually test statements using a WHERE clause:</p>
<blockquote>
<pre>SELECT * FROM world.City WHERE Population &gt; 1000000</pre>
</blockquote>
<p>The <strong>"Population &gt; 1000000"</strong> statement makes for a boolean expression. Using <strong>WHERE</strong> is just one way of evaluating it. One can also test with <a href="http://dev.mysql.com/doc/refman/5.1/en/control-flow-functions.html#function_if"><strong>IF()</strong></a>:</p>
<blockquote>
<pre>SET @val := 7;
SELECT IF(@val &gt; 2, 'Yes', 'No')</pre>
</blockquote>
<h4>TRUE and FALSE</h4>
<p>The two are keywords. They also map for the numerals <strong>1</strong> and <strong>0</strong>, as follows:</p>
<blockquote>
<pre>mysql&gt; SELECT TRUE, FALSE;
+------+-------+
| TRUE | FALSE |
+------+-------+
|    1 |     0 |
+------+-------+</pre>
</blockquote>
<p>Like in the <strong>C</strong> programming language, a nonzero value evaluates to a <em>true</em> value. A zero evaluates to <em>false</em>. A NULL evaluates to... well, NULL. But aside from 3-valued logic, what's important in our case is that it is <em>not true</em>.<span id="more-4198"></span></p>
<p>However, simple value comparison is incorrect:</p>
<blockquote>
<pre>mysql&gt; SELECT @val, @val &gt; 3, @val &gt; 3 = TRUE as result;
+------+----------+--------+
| @val | @val &gt; 3 | result |
+------+----------+--------+
|    7 |        1 |      1 |
+------+----------+--------+

mysql&gt; SELECT @val, @val = TRUE as result;
+------+--------+
| @val | result |
+------+--------+
|    7 |      0 |
+------+--------+</pre>
</blockquote>
<p>To test for the truth value of an expression, the correct syntax is by using <strong>IS TRUE</strong>:</p>
<blockquote>
<pre>SELECT @val, @val IS TRUE as result;
+------+--------+
| @val | result |
+------+--------+
|    7 |      1 |
+------+--------+</pre>
</blockquote>
<p>Likewise, one may use <strong>IS FALSE</strong> to test for falsehood. However, if you wish to note <strong>NULL</strong> as a <em>false</em> value this does not work:</p>
<blockquote>
<pre>SELECT @empty, @empty IS TRUE, @empty IS FALSE;
+--------+----------------+-----------------+
| @empty | @empty IS TRUE | @empty IS FALSE |
+--------+----------------+-----------------+
| NULL   |              0 |               0 |
+--------+----------------+-----------------+</pre>
</blockquote>
<p>If you're unsure why, you should read more on three-valued logic in SQL. To solve the above, simply use <strong>IS NOT TRUE</strong>:</p>
<blockquote>
<pre>SELECT @empty, @empty IS NOT TRUE;
+--------+--------------------+
| @empty | @empty IS NOT TRUE |
+--------+--------------------+
| NULL   |                  1 |
+--------+--------------------+</pre>
</blockquote>
<p>In summary, use <strong>IS TRUE</strong> and <strong>IS NOT TRUE</strong> so as to normalize truth values into a <strong>0</strong>, <strong>1</strong> value range, <strong>C</strong> style, including handling of <strong>NULL</strong>s.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/syntax-of-the-day-is-true-and-is-false/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>More MySQL foreach()</title>
		<link>http://code.openark.org/blog/mysql/more-mysql-foreach</link>
		<comments>http://code.openark.org/blog/mysql/more-mysql-foreach#comments</comments>
		<pubDate>Fri, 02 Dec 2011 13:55:32 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[Development]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[common_schema]]></category>
		<category><![CDATA[Hack]]></category>
		<category><![CDATA[INFORMATION_SCHEMA]]></category>
		<category><![CDATA[Open Source]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=4171</guid>
		<description><![CDATA[In my previous post I've shown several generic use cases for foreach(), a new scripting functionality introduced in common_schema. In this part I present DBA's handy syntax for schema and table operations and maintenance. Confession: while I love INFORMATION_SCHEMA's power, I just hate writing queries against it. It's just so much typing! Just getting the [...]]]></description>
			<content:encoded><![CDATA[<p>In my <a href="http://code.openark.org/blog/mysql/mysql-foreach">previous post</a> I've shown several generic use cases for <a href="http://common-schema.googlecode.com/svn/trunk/common_schema/doc/html/foreach.html"><em>foreach()</em></a>, a new scripting functionality introduced in <a href="http://code.google.com/p/common-schema/" rel="nofollow">common_schema</a>.</p>
<p>In this part I present DBA's handy syntax for schema and table operations and maintenance.</p>
<p>Confession: while I love <strong>INFORMATION_SCHEMA</strong>'s power, I just <em>hate</em> writing queries against it. It's just so much typing! Just getting the list of tables in a schema makes for this heavy duty query:</p>
<blockquote>
<pre>SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_SCHEMA='sakila' AND TABLE_TYPE='BASE TABLE';</pre>
</blockquote>
<p>When a join is involved this really becomes a nightmare. I think it's cumbersome, and as result, many do not remember the names and meaning of columns, making for <em>"oh, I need to read the manual all over again just to get that query right"</em>. Anyway, that's my opinion.</p>
<p>A <strong>SHOW TABLES</strong> statement is easier to type, but cannot be integrated into a <strong>SELECT</strong> query (though <a href="http://code.openark.org/blog/mysql/reading-results-of-show-statements-on-server-side">we have a partial solution</a> for that, too), and besides, when filtering out the views, the <strong>SHOW</strong> statement becomes almost as cumbersome as the one on <strong>INFORMATION_SCHEMA</strong>.</p>
<p>Which is why <em>foreach()</em> offers handy shortcuts to common iterations on schemata and tables, as follows:</p>
<h4>Use case: iterate all databases</h4>
<blockquote>
<pre>call foreach(<span style="color: #808000;">'schema'</span>, <span style="color: #003366;">'CREATE TABLE ${schema}.event(event_id INT, msg VARCHAR(128))'</span>);</pre>
</blockquote>
<p>In the above we execute a query on each database. Hmmm, maybe not such a good idea to perform this operation on all databases? Let's filter them:</p>
<h4>Use case: iterate databases by name match</h4>
<blockquote>
<pre>call foreach(<span style="color: #808000;">'schema like wordpress_%'</span>, <span style="color: #003366;">'ALTER TABLE ${schema}.wp_posts MODIFY COLUMN comment_author VARCHAR(96) NOT NULL'</span>);</pre>
</blockquote>
<p>The above will only iterate my WordPress databases (I have several of these), performing an <strong>ALTER</strong> on <strong>wp_posts</strong> for each of those databases.<span id="more-4171"></span></p>
<p>I don't have to quote the <em>like</em> expression, but I can, if I wish to.</p>
<p>I can also use a regular expression match:</p>
<blockquote>
<pre>call foreach(<span style="color: #808000;">'schema ~ /^wordpress_[0-9]+$/'</span>, <span style="color: #003366;">'ALTER TABLE ${schema}.wp_posts MODIFY COLUMN comment_author VARCHAR(96) NOT NULL'</span>);</pre>
</blockquote>
<h4>Use case: iterate tables in a specific schema</h4>
<p>Time to upgrade our <strong>sakila</strong> tables to InnoDB's compressed format. We use <strong>$()</strong>, a synonym for <em>foreach()</em>.</p>
<blockquote>
<pre>call $(<span style="color: #808000;">'table in sakila'</span>, <span style="color: #003366;">'ALTER TABLE ${schema}.${table} ENGINE=InnoDB ROW_FORMAT=COMPRESSED'</span>);</pre>
</blockquote>
<p>The above will iterate on tables in <strong>sakila</strong>. I say <em>tables</em>, since it will avoid iterating views (there is still no specific syntax for views iteration). This is done on purpose, as my experience shows there is very little in common between tables and views when it comes to maintenance and operations.</p>
<h4>Use case: iterate tables by name match</h4>
<p>Here's a interesting scenario: you wish to work on all tables matching some name. The naive approach would be to:</p>
<blockquote>
<pre>SELECT TABLE_SCHEMA, TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'wp_posts' AND TABLE_TYPE = 'BASE TABLE'</pre>
</blockquote>
<p><em><strong>Wait!</strong></em> Are you aware this may bring your server down? This query will open all databases at once, opening all <strong>.frm</strong> files (though thankfully not data files, since we only check for name and type).</p>
<p>Here's a better approach:</p>
<blockquote>
<pre>call foreach(<span style="color: #808000;">'table like wp_posts'</span>, <span style="color: #003366;">'ALTER TABLE ${schema}.${table} ENGINE=InnoDB'</span>);</pre>
</blockquote>
<p>(There's now FULLTEXT to InnoDB, so the above can make sense in the near future!)</p>
<p>The good part is that <em>foreach()</em> will look for matching tables <em>one database at a time</em>. It will iterate the list of database, then look for matching tables per database, thereby optimizing the query on <strong>INFORMATION_SCHEMA</strong>.</p>
<p>Here, too, I can use regular expressions:</p>
<blockquote>
<pre>call $(<span style="color: #808000;">'table ~ /^wp_.*$/'</span>, <span style="color: #003366;">'ALTER TABLE ${schema}.${table} ENGINE=InnoDB'</span>);</pre>
</blockquote>
<h4>Conclusion</h4>
<p>This is work in the making, but, as someone who maintains a few productions servers, I've already put it to work.</p>
<p>I'm hoping the syntax is easy to comprehend. I know that since I developed it it must be far more intuitive to myself than to others. I've tried to keep close on common syntax and concepts from various programming languages.</p>
<p>I would like to get as much feedback as possible. I have further ideas and thoughts on the direction <a href="http://code.google.com/p/common-schema/">common_schema</a> is taking, but wish take it in small steps. Your feedback is appreciated!</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/more-mysql-foreach/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>MySQL foreach()</title>
		<link>http://code.openark.org/blog/mysql/mysql-foreach</link>
		<comments>http://code.openark.org/blog/mysql/mysql-foreach#comments</comments>
		<pubDate>Fri, 02 Dec 2011 04:59:03 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[common_schema]]></category>
		<category><![CDATA[Hack]]></category>
		<category><![CDATA[scripts]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=4002</guid>
		<description><![CDATA[A new routine is now available in common_schema, which makes for an easier execution syntax for some operations: foreach(collection_to_iterate_over, queries_to_execute_per_iteration_step); To illustrate what it can do, consider: call foreach('table in sakila', 'ALTER TABLE ${schema}.${table} ENGINE=InnoDB ROW_FORMAT=COMPACT'); call $('schema like shard_%', 'CREATE TABLE ${schema}.messages (id INT)'); call $('2000:2009', 'INSERT IGNORE INTO report (report_year) VALUES (${1})'); $() [...]]]></description>
			<content:encoded><![CDATA[<p>A new routine is now available in <a href="http://code.google.com/p/common-schema/" rel="nofollow">common_schema</a>, which makes for an easier execution syntax for some operations:</p>
<blockquote>
<pre>foreach(<span style="color: #808000;"><em>collection_to_iterate_over</em></span>, <span style="color: #003366;"><em>queries_to_execute_per_iteration_step</em></span>);</pre>
</blockquote>
<p>To illustrate what it can do, consider:</p>
<blockquote>
<pre>call foreach(<span style="color: #808000;">'table in sakila'</span>, <span style="color: #000080;">'ALTER TABLE <strong>${schema}</strong>.<strong>${table}</strong> ENGINE=InnoDB ROW_FORMAT=COMPACT'</span>);

call $(<span style="color: #808000;">'schema like shard_%</span>', <span style="color: #000080;">'CREATE TABLE <strong>${schema}</strong>.messages (id INT)'</span>);

call $(<span style="color: #808000;">'2000:2009'</span>, <span style="color: #000080;">'INSERT IGNORE INTO report (report_year) VALUES (<strong>${1}</strong>)'</span>);</pre>
</blockquote>
<p><strong>$()</strong> stands as a synonym to <em>foreach()</em>. I suspect it should look familiar to web programmers.</p>
<p>The idea for <em>foreach()</em> was introduced by Giuseppe Maxia during a correspondence. At first I was skeptic: this isn't <a href="http://api.jquery.com/jQuery.each/">jQuery</a>; this is SQL. Why would I want to use <em>foreach()</em>?</p>
<p>Then Giuseppe provided some use cases, and as I started thinking about it, I found more and more cases where such a tool might considerably reduce scripting overhead and avoid requiring SQL-fu skills. In fact, I have been using it myself for the past few weeks</p>
<p>I provide examples which I hope will convince the reader as for the simplicity of using such syntax. Showing off the types of input <em>foreach()</em> accepts (query, table search, schema search, set of constants, single or double numbers range), and the types of queries it can execute (single, multiple, using placeholders).</p>
<p>I stress that this is not a replacement for common queries (i.e. does <em>not</em> come to replace your common <strong>SELECT</strong>, <strong>UPDATE</strong>, <strong>DELETE</strong>), but more for working out administrative tasks. Nevertheless, the last example in this post does provide with an interesting insight on possible "normal" use.<span id="more-4002"></span></p>
<h4>Use case: using values from query</h4>
<p>Let's kill all queries running for over <strong>20</strong> seconds:</p>
<blockquote>
<pre>call foreach(<span style="color: #808000;">'SELECT id FROM INFORMATION_SCHEMA.PROCESSLIST WHERE time &gt; 20'</span>, <span style="color: #000080;">'KILL QUERY <strong>${1}</strong>'</span>);</pre>
</blockquote>
<p>The thing I like most about <em>foreach()</em> is that it's self explanatory. Nevertheless, I note:</p>
<ul>
<li>The <strong>KILL</strong> command is executed for each process running for more than <strong>20</strong> seconds (I did round up corners, since I didn't check for sleeping processes, for simplicity).</li>
<li>I also use the <strong>${1}</strong> placeholder: much like in <em>awk</em>, this will get the first column in the result set. In our case, it is the single column, <strong>id</strong>.</li>
<li>I chose to invoke a single query/command per iteration step.</li>
</ul>
<p>Compare the above with another solution to the same problem, using <a href="http://code.openark.org/blog/mysql/mysql-eval">eval()</a>:</p>
<blockquote>
<pre>call eval('SELECT CONCAT(\'KILL QUERY \',id) FROM INFORMATION_SCHEMA.PROCESSLIST WHERE TIME &gt; 20');</pre>
</blockquote>
<p>They both get the same thing done. But <em>foreach()</em> is just a bit more friendly to write (and read).</p>
<p>Let's move to a more complicated example.</p>
<h4>Use case: using multiple values from a query, invoking multiple commands</h4>
<p>Let's kill some queries, as above, but also write down a log entry so that we know what happened:</p>
<blockquote>
<pre>call foreach(
  <span style="color: #808000;">'SELECT id, user FROM INFORMATION_SCHEMA.PROCESSLIST WHERE time &gt; 20'</span>,
  <span style="color: #000080;">'KILL QUERY <strong>${1}</strong>; INSERT INTO my_log VALUES (\'have just killed query <strong>${1}</strong>, executed by <strong>${2}</strong>\');'</span>)
;</pre>
</blockquote>
<p>In the above, for each long running process, we:</p>
<ul>
<li>Kill the process' query. <strong>id</strong> being the first column, is referenced by <strong>${1}</strong>.</li>
<li>INSERT to my_log that said process has been killed. We note both <strong>id</strong> and <strong>user</strong> using placeholders <strong>${1}</strong> and <strong>${2}</strong>, respectively.</li>
</ul>
<p>It's possible to invoke as many queries/commands per iteration step. It is possible to use placeholders <strong>${1}</strong> through <strong>${9}</strong>, as well as <strong>${NR}</strong>, which works as in <em>awk</em>: it is a row-counter, <strong>1</strong>-based.</p>
<p>This example can still be written with <em>eval()</em>, but in much uglier form. I can't just first <strong>KILL</strong> the processes, then log about them, since by the time I want to log, the queries will not be running; the commands <em>must be coupled</em>. This is naturally done with <em>foreach()</em>.</p>
<h4>Use case: iterating constant values, invoking DDL</h4>
<p>The commands invoked by <em>foreach()</em> can take the form of DML (<strong>INSERT</strong>/<strong>UPDATE</strong>/...), DDL (<strong>CREATE</strong>/<strong>ALTER</strong>/...) or other (<strong>KILL</strong>/<strong>SET</strong>/...). The placeholders can be used anywhere within the text.</p>
<p>Take an installation where different schemata have the same exact table structure. We want to refactor a table on all schemata:</p>
<blockquote>
<pre>call $(<span style="color: #808000;">'<strong>{USA, UK, Japan, NZ}</strong>'</span>, <span style="color: #000080;">'ALTER TABLE db_region_<strong>${1}</strong>.customer ADD COLUMN personal_notes VARCHAR(4096) CHARSET utf8'</span>);</pre>
</blockquote>
<p>The above translates to the following commands:</p>
<blockquote>
<pre>ALTER TABLE <strong>db_region_USA</strong>.customer ADD COLUMN personal_notes VARCHAR(4096) CHARSET utf8;
ALTER TABLE <strong>db_region_UK</strong>.customer ADD COLUMN personal_notes VARCHAR(4096) CHARSET utf8;
ALTER TABLE <strong>db_region_Japan</strong>.customer ADD COLUMN personal_notes VARCHAR(4096) CHARSET utf8;
ALTER TABLE <strong>db_region_NZ</strong>.customer ADD COLUMN personal_notes VARCHAR(4096) CHARSET utf8;</pre>
</blockquote>
<p>In the above, we:</p>
<ul>
<li>Provide a list of constant values. These can be strings, numbers, whatever. They are space delimited.</li>
<li>Use the <strong>${1}</strong> place holder. We can also use <strong>${NR}</strong>.</li>
</ul>
<h4>Use case: loop through number sequence</h4>
<p>We wish to populate a table with values:</p>
<blockquote>
<pre>call foreach(<span style="color: #808000;">'<strong>1970:2038</strong>'</span>, <span style="color: #003366;">'INSERT INTO test.test_dates (dt) VALUES (DATE(\'<strong>${1}</strong>-01-01\'))'</span>);</pre>
</blockquote>
<p>The above results with:</p>
<blockquote>
<pre>mysql&gt; SELECT dt FROM test_dates;
+------------+
| dt         |
+------------+
| 1970-01-01 |
| 1971-01-01 |
| 1972-01-01 |
| 1973-01-01 |
| 1974-01-01 |
...
| 2036-01-01 |
| 2037-01-01 |
| 2038-01-01 |
+------------+</pre>
</blockquote>
<p>With numbers range:</p>
<ul>
<li>Integers are assumed</li>
<li>Range is indicated by low and high values, both inclusive</li>
<li>Negatives allowed (e.g. <strong>'-5:5'</strong>, resulting with <strong>11</strong> steps)</li>
<li>Placeholders <strong>${1}</strong> and <strong>${NR}</strong> are allowed.</li>
</ul>
<h4>Use case: iterating through two dimensional numbers range:</h4>
<p>We use <strong>3</strong> template tables; we create <strong>15</strong> schemata; in each we create <strong>3</strong> tables based on the template tables:</p>
<blockquote>
<pre>call foreach(<span style="color: #808000;"><strong> '1:15,1:3'</strong></span>,
  <span style="color: #003366;">'CREATE DATABASE IF NOT EXISTS db_test_${1}; CREATE TABLE db_test_${1}.tbl_${2} LIKE db_template.my_table_${2};'</span>
);</pre>
</blockquote>
<p>Notes:</p>
<ul>
<li>Each of the number ranges has the same restrictions and properties as listed above (integers, inclusive, ascending)</li>
<li>We can now use <strong>${1}</strong> and <strong>${2}</strong> placeholders, noting the first and second numbers range, respectively.</li>
<li>We may also use <strong>${NR}</strong>, which, in this case, will run <strong>1</strong> through <strong>45</strong> (<strong>15</strong> times <strong>3</strong>).</li>
<li>We use multiple queries per iteration step.</li>
</ul>
<h4>Use case: overcoming MySQL limitations</h4>
<p>MySQL does not support <strong>ORDER BY</strong> &amp; <strong>LIMIT</strong> in multi-table <strong>UPDATE</strong> and <strong>DELETE</strong> statements (as noted <a href="http://code.openark.org/blog/mysql/three-wishes-for-a-new-year">last year</a>). So we <em>cannot</em>:</p>
<blockquote>
<pre>DELETE FROM t1 USING t1 JOIN t2 ON (...) JOIN t3 ON (..) WHERE x = 7 ORDER BY ts LIMIT 100;</pre>
</blockquote>
<p>However, we <em>can</em>:</p>
<blockquote>
<pre>call foreach(
  <span style="color: #808000;">'SELECT t1.id FROM t1 JOIN t2 ON (...) JOIN t3 ON (..) WHERE x = 7 ORDER BY ts LIMIT 100'</span>,
  <span style="color: #003366;">'DELETE FROM t1 WHERE id = ${1}'</span>
);</pre>
</blockquote>
<p>Of course, it will do a lot of single row <strong>DELETE</strong>s. There are further MySQL limitations which complicate things if I want to overcome this. Perhaps at a later blog post.</p>
<h4>Acknowledgements</h4>
<p>I hit a weird <a href="http://bugs.mysql.com/bug.php?id=62406">bug</a> which prevented me from releasing this earlier on. Actually it's a duplicate of <a href="http://bugs.mysql.com/bug.php?id=12257">this bug</a>, which makes it <strong>6</strong> years old. Hurray.</p>
<p>To the rescue came <a href="http://rpbouman.blogspot.com/">Roland Bouman</a>, who suggested an idea so crazy even I was skeptic: to parse and modify the original query so as to rename column names according to my scheme. And of course he made it happen, along with some additional very useful stuff. It's really a <em>super-ultra-meta-meta-sql-fu</em> magic he does there.</p>
<p>So, thanks, Roland, for joining the ride, and thanks, Giuseppe, for testing and helping out to shape this functionality. It's great fun working with other people on open-source -- a new experience for me.</p>
<h4>Continued</h4>
<p>In this post I've covered the general-purpose iterations. There are also more specific types of iterations with <em>foreach()</em>. <a href="http://code.openark.org/blog/mysql/more-mysql-foreach">Continued next</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/mysql-foreach/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Reading results of SHOW statements, on server side</title>
		<link>http://code.openark.org/blog/mysql/reading-results-of-show-statements-on-server-side</link>
		<comments>http://code.openark.org/blog/mysql/reading-results-of-show-statements-on-server-side#comments</comments>
		<pubDate>Fri, 25 Nov 2011 19:39:58 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[common_schema]]></category>
		<category><![CDATA[Hacks]]></category>
		<category><![CDATA[INFORMATION_SCHEMA]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=4138</guid>
		<description><![CDATA[SHOW statements are show stoppers on server side. While clients can get a SHOW statement as a result set just as any normal SELECT, things are not as such on server side. On server side, that is, from within MySQL itself, one cannot: SELECT `Database` FROM (SHOW DATABASES); One cannot: DECLARE show_cursor CURSOR FOR SHOW [...]]]></description>
			<content:encoded><![CDATA[<p><strong>SHOW</strong> statements are show stoppers on server side. While clients can get a <a href="http://dev.mysql.com/doc/refman/5.1/en/show.html">SHOW statement</a> as a result set just as any normal <strong>SELECT</strong>, things are not as such on server side.</p>
<p>On server side, that is, from within MySQL itself, one <em>cannot</em>:</p>
<blockquote>
<pre>SELECT `Database` FROM (SHOW DATABASES);</pre>
</blockquote>
<p>One <em>cannot</em>:</p>
<blockquote>
<pre>DECLARE show_cursor CURSOR FOR SHOW TABLES;</pre>
</blockquote>
<p>One <em>cannot</em>:</p>
<blockquote>
<pre>SHOW TABLES INTO OUTFILE '/tmp/my_file.txt';</pre>
</blockquote>
<p>So it is impossible to get the results with a query; impossible to get the results from a stored routine; impossible to get the results by file reading...</p>
<h4>Bwahaha! A hack!</h4>
<p>For some <strong>SHOW</strong> statements, there is a way around this. I've been banging my head against the wall for weeks now on this. Now I have a partial solution: I'm able to read <strong>SHOW</strong> output for several <strong>SHOW</strong> statements. Namely, those <strong>SHOW</strong> statements <a href="http://dev.mysql.com/doc/refman/5.1/en/extended-show.html">which allow a LIKE or a WHERE</a> clause.</p>
<p>For example, most are familiar with the following syntax:</p>
<blockquote>
<pre>USE mysql;
SHOW TABLE STATUS LIKE 'user';</pre>
</blockquote>
<p>However not so many know that any <strong>SHOW</strong> statement which accepts <strong>LIKE</strong>, can also accept <strong>WHERE</strong>:<span id="more-4138"></span></p>
<blockquote>
<pre>SHOW TABLE STATUS WHERE Name='user'\G
*************************** 1. row ***************************
           Name: user
         Engine: MyISAM
        Version: 10
     Row_format: Dynamic
           Rows: 17
 Avg_row_length: 69
    Data_length: 1184
Max_data_length: 281474976710655
   Index_length: 2048
      Data_free: 0
 Auto_increment: NULL
    Create_time: 2010-10-03 08:23:48
    Update_time: 2011-07-30 19:31:00
     Check_time: NULL
      Collation: utf8_bin
       Checksum: NULL
 Create_options:
        Comment: Users and global privileges</pre>
</blockquote>
<p>It's not just about "<strong>Name</strong>". I can filter using any column I like:</p>
<blockquote>
<pre>SHOW TABLE STATUS WHERE Rows &gt; 1000;
SHOW TABLE STATUS WHERE Rows &gt; 1000 AND Index_length &gt; 65536;</pre>
</blockquote>
<p>etc.</p>
<p>If you've been to my talk on <a href="http://www.percona.com/live/london-2011/session/programmatic-queries-things-you-can-code-with-sql/">Programmatic Queries: things you can code with SQL</a>, you have a good guess as for where I'm taking this.</p>
<h4>Where there's WHERE, there's code</h4>
<p>I can write code within the <strong>WHERE</strong> clause. Specifically, I can work with user defined variables. Shall we cut to the point and provide with an example?</p>
<blockquote>
<pre>mysql&gt; SET @databases := '';

mysql&gt; SHOW DATABASES WHERE (@databases := CONCAT(@databases, `Database`, ',')) IS NULL;

mysql&gt; SELECT @databases;
+-------------------------------------------------------------------+
| @databases                                                        |
+-------------------------------------------------------------------+
| information_schema,common_schema,mycheckpoint,mysql,sakila,world, |
+-------------------------------------------------------------------+</pre>
</blockquote>
<p>Let's discuss the above. We:</p>
<ul>
<li>Set a user variables called <strong>@databases</strong> to an empty text</li>
<li>Iterate through the <strong>SHOW DATABASES</strong> rowset. The <strong>WHERE</strong> clause is always <em>false</em> (the expression is in fact <strong>NOT NULL</strong> for all rows), so rows are not printed out, and we get an empty result set (we're not really interested in a result set here, since there's no way to read it anyhow).</li>
<li>However we do take care to "remember" the value we visit, by concatenating the <strong>`Database`</strong> column value.</li>
<li>We end up with a delimited string of database names. You'll forgive the ending <strong>','</strong>. This is just a simple example, it is of no importance.</li>
</ul>
<h4>Further notes</h4>
<p>What can we do with the concatenated list of database names? Whatever we want to. We can parse it again, <strong>INSERT</strong> it <strong>INTO</strong> some table, save to file, iterate, what have you!</p>
<p>We can wrap the above in a stored routine. Alas, not with a stored function, since the <strong>SHOW</strong> command, although returns with an empty result set, does return with a result set, not allowed withing functions.<strong></strong></p>
<h4>Limitations</h4>
<ul>
<li>Sadly, <strong>SHOW SLAVE STATUS</strong>, <strong>SHOW MASTER LOGS</strong> etc., do not support <strong>LIKE</strong> or <strong>WHERE</strong> syntax. Bummer.</li>
<li>Stored functions, as just mentioned, cannot utilize this hack. Hey, I'm still working on this!</li>
</ul>
<h4>To what use?</h4>
<p>Originally I wanted to avoid the time &amp; locking it takes for <strong>INFORMATION_SCHEMA</strong> queries, such as on <strong>TABLES</strong>, <strong>COLUMNS</strong>, etc. Ironically, in a few days apart I've found <em>another</em> interesting solution (well, two, actually) to manage reads from <strong>INFORMATION_SCHEMA</strong> with less overhead than in normal use. I'll talk about that another time; am about to use this in <a href="http://code.google.com/p/common-schema/" rel="nofollow">common_schema</a>.</p>
<h4>Further notes</h4>
<p>I met <a href="http://rpbouman.blogspot.com/">Roland</a> in <a href="http://www.percona.com/live/london-2011/">London</a>, and he liked the solution. As <a href="http://www.mysqlperformanceblog.com/author/baron/">Baron</a> joined, Roland said: "Baron, do you know Shlomi devised a method to read the output of <strong>SHOW</strong> commands?"</p>
<p>And Baron said: "Without using files? Then a <strong>SHOW</strong> statement can have a <strong>WHERE</strong> clause, in which case you can use a variable", and went on looking for his wife.</p>
<p>And we remained speechless.</p>
<p>[UPDATE: I've manually changed timestamp of this post due to failure in its aggregation in planet.mysql, being a major source of incoming traffic to this site]</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/reading-results-of-show-statements-on-server-side/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		</item>
		<item>
		<title>Quoting text JavaScript/Python style</title>
		<link>http://code.openark.org/blog/mysql/quoting-text-javascriptpython-style</link>
		<comments>http://code.openark.org/blog/mysql/quoting-text-javascriptpython-style#comments</comments>
		<pubDate>Tue, 15 Nov 2011 06:11:37 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Syntax]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=4364</guid>
		<description><![CDATA[Unless your MySQL is configured to use ANSI_QUOTES in sql_mode, you are able to quote your text in one of two forms: using single quotes or double quotes: UPDATE world.Country SET HeadOfState = 'Willy Wonka' WHERE Code='USA' UPDATE world.Country SET HeadOfState = "Willy Wonka" WHERE Code="USA" This makes for JavaScript- or Python-style quoting: you quote [...]]]></description>
			<content:encoded><![CDATA[<p>Unless your MySQL is configured to use <a href="http://dev.mysql.com/doc/refman/5.1/en/server-sql-mode.html#sqlmode_ansi_quotes"><strong>ANSI_QUOTES</strong></a> in <strong>sql_mode</strong>, you are able to quote your text in one of two forms: using single quotes or double quotes:</p>
<blockquote>
<pre>UPDATE world.Country SET HeadOfState = <strong>'Willy Wonka'</strong> WHERE Code=<strong>'USA'</strong>
UPDATE world.Country SET HeadOfState = <strong>"Willy Wonka"</strong> WHERE Code=<strong>"USA"</strong></pre>
</blockquote>
<p>This makes for JavaScript- or Python-style quoting: you quote by your needs. Say you have a text which includes single quotes:</p>
<blockquote><p><em>It is what you read when you don't have to that determines what you will be when you can't help it.</em> - Oscar Wilde</p></blockquote>
<p>You wish to insert this text to some tables. You could go through the trouble of escaping it:</p>
<blockquote>
<pre>INSERT INTO quotes (quote, author) VALUES (
  'It is what you read when you don\'t have to that determines what you will be when you can\'t help it.', 'Oscar Wilde');</pre>
</blockquote>
<p>or you could just wrap it in double quotes:</p>
<blockquote>
<pre>INSERT INTO quotes (quote, author) VALUES (
  "It is what you read when you don't have to that determines what you will be when you can't help it.", 'Oscar Wilde');</pre>
</blockquote>
<p>I find this useful when using SQL to generate queries. Take, for example, <a href="http://code.openark.org/blog/mysql/mysql-eval">eval() for MySQL</a>: the statement:<span id="more-4364"></span></p>
<blockquote>
<pre>CALL eval('select concat(\'KILL \',id) from information_schema.processlist where user=\'webuser\'');</pre>
</blockquote>
<p>is just so more easily written this way:</p>
<blockquote>
<pre>CALL eval("select concat('KILL ',id) from information_schema.processlist where user='webuser'");</pre>
</blockquote>
<p>I don't suggest one should use this method throughout her application code. Application code works great with auto-escaping string literals. But for the handy DBA or developer, who needs to work some quick queries by hand, this makes for an easier syntax to use.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/quoting-text-javascriptpython-style/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Self throttling MySQL queries</title>
		<link>http://code.openark.org/blog/mysql/self-throttling-mysql-queries</link>
		<comments>http://code.openark.org/blog/mysql/self-throttling-mysql-queries#comments</comments>
		<pubDate>Tue, 01 Nov 2011 07:55:47 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Hack]]></category>
		<category><![CDATA[MyISAM]]></category>
		<category><![CDATA[Performance]]></category>
		<category><![CDATA[SQL]]></category>
		<category><![CDATA[Stored routines]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=4294</guid>
		<description><![CDATA[Recap on the problem: A query takes a long time to complete. During this time it makes for a lot of I/O. Query's I/O overloads the db, making for other queries run slow. I introduce the notion of self-throttling queries: queries that go to sleep, by themselves, throughout the runtime. The sleep period means the [...]]]></description>
			<content:encoded><![CDATA[<p>Recap on the problem:</p>
<ul>
<li>A query takes a long time to complete.</li>
<li>During this time it makes for a lot of I/O.</li>
<li>Query's I/O overloads the db, making for other queries run slow.</li>
</ul>
<p>I introduce the notion of self-throttling queries: queries that go to sleep, by themselves, throughout the runtime. The sleep period means the query does not perform I/O at that time, which then means other queries can have their chance to execute.</p>
<p>I present two approaches:</p>
<ul>
<li>The naive approach: for every <strong>1,000</strong> rows, the query sleep for <strong>1</strong> second</li>
<li>The factor approach: for every <strong>1,000</strong> rows, the query sleeps for the amount of time it took to iterate those <strong>1,000</strong> rows (effectively doubling the total runtime of the query).<span id="more-4294"></span></li>
</ul>
<h4>Sample query</h4>
<p>We use a simple, single-table scan. No aggregates (which complicate the solution considerably).</p>
<blockquote>
<pre>SELECT
  rental_id,
  TIMESTAMPDIFF(DAY, rental_date, return_date) AS rental_days
FROM
  sakila.rental
;</pre>
</blockquote>
<h4>The naive solution</h4>
<p>We need to know every <strong>1,000</strong> rows. So we need to count the rows. We do that by using a counter, as follows:</p>
<blockquote>
<pre>SELECT
  rental_id,
  TIMESTAMPDIFF(DAY, rental_date, return_date) AS rental_days,
  @row_counter := @row_counter + 1
FROM
  sakila.rental,
  (SELECT @row_counter := 0) sel_row_counter
;</pre>
</blockquote>
<p>A thing that bothers me, is that I wasn't asking for an additional column. I would like the result set to remain as it were; same result structure. We also want to sleep for <strong>1</strong> second for each <strong>1,000</strong> rows. So we merge the two together along with one of the existing columns, like this:</p>
<blockquote>
<pre>SELECT
  rental_id +
    IF(
      (@row_counter := @row_counter + 1) % 1000 = 0,
      SLEEP(1), 0
    ) AS rental_id,
  TIMESTAMPDIFF(DAY, rental_date, return_date) AS rental_days
FROM
  sakila.rental,
  (SELECT @row_counter := 0) sel_row_counter
;</pre>
</blockquote>
<p>To remain faithful to <a href="http://code.openark.org/blog/mysql/slides-from-my-talk-programmatic-queries-things-you-can-code-with-sql">my slides</a>, I rewrite as follows, and this is <em>the naive solution</em>:</p>
<blockquote>
<pre>SELECT
  rental_id +
    CASE
      WHEN <strong>(@row_counter := @row_counter + 1) % 1000 = 0</strong> THEN <strong>SLEEP(1)</strong>
      ELSE <strong>0</strong>
    END AS rental_id,
  TIMESTAMPDIFF(DAY, rental_date, return_date) AS rental_days
FROM
  sakila.rental,
  (SELECT @row_counter := 0) sel_row_counter
;</pre>
</blockquote>
<p>The <strong>WHEN</strong> clause always returns <strong>0</strong>, so it does not affect the value of <strong>rental_id</strong>.</p>
<h4>The factor approach</h4>
<p>In the factor approach we wish to keep record of query execution, every <strong>1,000</strong> rows. I introduce a nested <strong>WHEN</strong> statement which updates time records. I rely on <strong>SYSDATE()</strong> to return the true time, and on <strong>NOW()</strong> to return query execution start time.</p>
<blockquote>
<pre>SELECT
  rental_id +
    CASE
      WHEN (@row_counter := @row_counter + 1) IS NULL THEN NULL
      WHEN <strong>@row_counter % 1000 = 0</strong> THEN
        CASE
          WHEN (@time_now := <strong>SYSDATE()</strong>) IS NULL THEN NULL
          WHEN (@time_diff := (<strong>TIMESTAMPDIFF(SECOND, @chunk_start_time, @time_now)</strong>)) IS NULL THEN NULL
          WHEN <strong>SLEEP(@time_diff)</strong> IS NULL THEN NULL
          WHEN (@chunk_start_time := <strong>SYSDATE()</strong>) IS NULL THEN NULL
          ELSE 0
        END
      ELSE 0
    END AS rental_id,
  TIMESTAMPDIFF(DAY, rental_date, return_date) AS rental_days
FROM
  sakila.rental,
  (SELECT @row_counter := 0) sel_row_counter,
  (SELECT @chunk_start_time := NOW()) sel_chunk_start_time
;</pre>
</blockquote>
<h4>Proof</h4>
<p>How can we prove that the queries do indeed work?</p>
<p>We can see if the total runtime sums up to the number of sleep calls, in seconds; but how do we know that sleeps do occur at the correct times?</p>
<p>A solution I offer is to use a stored routines which logs to a MyISAM table (a non transactional table) the exact time (using <strong>SYSDATE()</strong>) and value per row. The following constructs are introduced:</p>
<blockquote>
<pre><strong>CREATE TABLE</strong> test.proof(
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  dt DATETIME NOT NULL,
  msg VARCHAR(255)
) <strong>ENGINE=MyISAM</strong>;

DELIMITER $$
<strong>CREATE FUNCTION</strong> test.prove_it(message VARCHAR(255)) RETURNS TINYINT
DETERMINISTIC
MODIFIES SQL DATA
BEGIN
  <strong>INSERT INTO test.proof (dt, msg) VALUES (SYSDATE(), message); RETURN 0;</strong>
END $$
DELIMITER ;</pre>
</blockquote>
<p>The <strong>prove_it()</strong> function records the immediate time and a message into the MyISAM table, which immediately accepts the write, being non-transactional. It returns with <strong>0</strong>, so we will now embed it within the query. Of course, the function itself incurs some overhead, but it will nevertheless convince you that <strong>SLEEP()</strong>s do occur at the right time!</p>
<blockquote>
<pre>SELECT
  rental_id +
    CASE
      WHEN (@row_counter := @row_counter + 1) IS NULL THEN NULL
      WHEN @row_counter % 1000 = 0 THEN
        CASE
          WHEN (@time_now := SYSDATE()) IS NULL THEN NULL
          WHEN (@time_diff := (TIMESTAMPDIFF(SECOND, @chunk_start_time, @time_now))) IS NULL THEN NULL
          WHEN SLEEP(@time_diff)<strong> + test.prove_it(CONCAT('will sleep for ', @time_diff, ' seconds'))</strong> IS NULL THEN NULL
          WHEN (@chunk_start_time := SYSDATE()) IS NULL THEN NULL
          ELSE 0
        END
      ELSE 0
    END AS rental_id,
  TIMESTAMPDIFF(DAY, rental_date, return_date) AS rental_days
FROM
  sakila.rental,
  (SELECT @row_counter := 0) sel_row_counter,
  (SELECT @chunk_start_time := NOW()) sel_chunk_start_time
;

mysql&gt; SELECT * FROM test.proof;
+----+---------------------+--------------------------+
| id | dt                  | msg                      |
+----+---------------------+--------------------------+
|  1 | 2011-11-01 09:22:36 | will sleep for 1 seconds |
|  2 | 2011-11-01 09:22:36 | will sleep for 0 seconds |
|  3 | 2011-11-01 09:22:36 | will sleep for 0 seconds |
|  4 | 2011-11-01 09:22:36 | will sleep for 0 seconds |
|  5 | 2011-11-01 09:22:36 | will sleep for 0 seconds |
|  6 | 2011-11-01 09:22:36 | will sleep for 0 seconds |
|  7 | 2011-11-01 09:22:38 | will sleep for 1 seconds |
|  8 | 2011-11-01 09:22:38 | will sleep for 0 seconds |
|  9 | 2011-11-01 09:22:38 | will sleep for 0 seconds |
| 10 | 2011-11-01 09:22:38 | will sleep for 0 seconds |
| 11 | 2011-11-01 09:22:38 | will sleep for 0 seconds |
| 12 | 2011-11-01 09:22:40 | will sleep for 1 seconds |
| 13 | 2011-11-01 09:22:40 | will sleep for 0 seconds |
| 14 | 2011-11-01 09:22:40 | will sleep for 0 seconds |
| 15 | 2011-11-01 09:22:40 | will sleep for 0 seconds |
+----+---------------------+--------------------------+</pre>
</blockquote>
<p>The above query is actually very fast. Try adding <strong>BENCHMARK(1000,ENCODE('hello','goodbye'))</strong> to rental_id so as to make it slower, or just use it on a really large table, see what happens (this is what I actually used to make the query run for several seconds in the example above).</p>
<p>Observant reads will note that the <strong>"will sleep..."</strong> message actually gets written <em>after</em> the <strong>SLEEP()</strong> call. I leave this as it is.</p>
<p>Another very nice treat of the code is that you don't need sub-second resolution for it to work. If you look at the above, we don't actually go to sleep every <strong>1,000</strong> rows (<strong>1,000</strong> is just too quick in the query -- perhaps I should have used <strong>10,000</strong> seconds). But we <em>do</em> make it once a second has <em>elapsed</em>. Which means it works correctly <em>on average</em>. Of course, the entire discussion is only of interest when a query executes for a <em>substantial</em> number of seconds, so this is just an anecdote.</p>
<h4>And the winner is...</h4>
<p>Wow, this <a href="http://code.openark.org/blog/mysql/contest-for-glory-write-a-self-throttling-mysql-query">contest</a> was anything but popular. <strong><a href="http://marcalff.blogspot.com/">Marc Alff</a></strong> is the obvious winner: he is the <em>only</em> one to suggest a solution <img src='http://code.openark.org/blog/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>But Marc uses a very nice trick: he reads the <strong>PERFORMANCE_SCHEMA</strong>. Now, I'm not sure how the <strong>PERFORMANCE_SCHEMA</strong> gets updated. I know that the <strong>INFORMATION_SCHEMA.GLOBAL_STATUS</strong> table does not get updated by a query until the query completes (so you cannot expect a change in <strong>innodb_rows_read</strong> throughout the execution of the query). I just didn't test it (homework, anyone?). If it does get updated, then we can throttle the query based on InnoDB page reads using a simple query. Otherwise, an access to <strong>/proc/diskstats</strong> is possible, assuming no <em>apparmor</em> or <em>SELinux</em> are blocking us.</p>
<p>Marc also uses a stored function, which is the <em>clean</em> way of doing it; however I distrust the overhead incurred by s stored routine and prefer my solution (which is, admittedly, not a pretty SQL sight!).</p>
<p>Happy throttling!</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/self-throttling-mysql-queries/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Contest for Glory: write a self throttling MySQL query</title>
		<link>http://code.openark.org/blog/mysql/contest-for-glory-write-a-self-throttling-mysql-query</link>
		<comments>http://code.openark.org/blog/mysql/contest-for-glory-write-a-self-throttling-mysql-query#comments</comments>
		<pubDate>Thu, 27 Oct 2011 17:20:30 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[community]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=4245</guid>
		<description><![CDATA[What's all this about? I've you've been to my talk in London, then you've already got this as homework. If not, allow me to fill in the details: I was speaking about MySQL's programmatic nature in many aspects (best if you read the slides!). We discussed user defined variables, derived tables, ordering constructs, order of [...]]]></description>
			<content:encoded><![CDATA[<p>What's all this about?</p>
<p>I've you've <a href="http://code.openark.org/blog/mysql/slides-from-my-talk-programmatic-queries-things-you-can-code-with-sql">been to my talk</a> in London, then you've already got this as homework. If not, allow me to fill in the details:</p>
<p>I was speaking about MySQL's programmatic nature in many aspects (best if you read the slides!). We discussed user defined variables, derived tables, ordering constructs, order of evaluation, time suspension and time calculation.</p>
<p>An issue I presented was that of a very long running query. Say it runs for <strong>20</strong> minutes. It kills your I/O. Do you <strong>KILL</strong> the query or wait? It <em>could</em> terminate in <strong>5</strong> seconds from now, and if you kill it now, you lose everything. But it may yet run for <strong>3</strong> more hours!</p>
<p>We discussed a futuristic feature where the query would gracefully terminate after some designated time. However, futuristic wishes do not help us.</p>
<h4>A self throttling query</h4>
<p>I suggested the idea for a self throttling query. We know how to throttle writing queries, such as <strong>DELETE</strong> queries: we break them into small chunks, then work each chunk at a time, setting ourselves to sleep in between chunks. This is how <strong>--sleep</strong> and <strong>--sleep-ratio</strong> work in <a href="http://openarkkit.googlecode.com/svn/trunk/openarkkit/doc/html/oak-chunk-update.html">oak-chunk-update</a>. It is how <strong>--sleep</strong> and<strong> --sleep-coef</strong> work in <a href="http://www.percona.com/doc/percona-toolkit/pt-archiver.html">pt-archiver</a>.</p>
<p>But can the same be done for <strong>SELECT</strong> queries?<span id="more-4245"></span></p>
<p>The answer is: yes. And it can be done from within the query itself. And it's your job to do it.</p>
<p>So here are the rules:</p>
<ul>
<li>For simplicity, assume the <strong>SELECT</strong> executes over a single large table.</li>
<li>We assume no <strong>GROUP BY</strong>, <strong>DISTINCT</strong> and the like.</li>
<li>There can be <strong>WHERE</strong>, <strong>ORDER BY</strong> etc.</li>
</ul>
<p>As an example:</p>
<blockquote>
<pre>SELECT rental_id, TIMESTAMPDIFF(DAY, rental_date, return_date) AS rental_days FROM sakila.rental</pre>
</blockquote>
<p>Here is the problem:</p>
<ul>
<li>The query takes too much disk I/O</li>
</ul>
<p>Suggestion: make the query self throttling. We're going to make it run for a <em>longer</em> time, allowing for non-I/O periods within the query. We assume we are not bothered with locks.</p>
<h4>Task #1</h4>
<ul>
<li>Write a self throttling query: rewrite the query above such that for every <strong>1,000</strong> rows, it goes to sleep for <strong>2</strong> seconds.</li>
</ul>
<h4>Task #2</h4>
<ul>
<li>Improve upon the previous solution: rewrite the query such that for every <strong>1,000</strong> rows, it goes to sleep for the same amount of time it took for those <strong>1,000</strong> rows to execute (effectively doubling the execution time of the query).</li>
</ul>
<h4>Advanced</h4>
<ul>
<li>There are issues with security, but in principal it is possible to have the query go to sleep when actual disk I/O exceeds some value. Code it!</li>
</ul>
<h4>Prove it</h4>
<p>devise a method to <em>prove</em> that sleeps do occur as required.</p>
<h4>How to submit a solution?</h4>
<ul>
<li>Simplest is to add as comment on this post. Use <strong>&lt;pre&gt;...&lt;/pre&gt;</strong> for formatted code.</li>
<li>You may also email me directly.</li>
</ul>
<p>I will pick up the best solution according to correctness, elegance and time of submission.</p>
<p>The winners get <em><strong>glory</strong></em>: their names to be mentioned on this blog. Shall we save the discussion on the exact font face and size for later on?</p>
<p><em><strong>UPDATE:</strong> it should have been clear from my talk: no stored routines involved!</em></p>
<p><em><strong>UPDATE</strong></em>: solution is on: <a href="http://code.openark.org/blog/mysql/self-throttling-mysql-queries">Self throttling MySQL queries</a></p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/contest-for-glory-write-a-self-throttling-mysql-query/feed</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Slides from my talk: &quot;Programmatic Queries: things you can code with SQL&quot;</title>
		<link>http://code.openark.org/blog/mysql/slides-from-my-talk-programmatic-queries-things-you-can-code-with-sql</link>
		<comments>http://code.openark.org/blog/mysql/slides-from-my-talk-programmatic-queries-things-you-can-code-with-sql#comments</comments>
		<pubDate>Thu, 27 Oct 2011 11:44:45 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Speaking]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=4243</guid>
		<description><![CDATA[Here are the slides from my talk Programmatic Queries: things you can code with SQL held on October 25th on the Percona Live event, London. Programmatic Queries: PDF I wish to thank those who attended my talk. The topic of the talk was irregular and, to some extent, controversial. Should one really rely on internal [...]]]></description>
			<content:encoded><![CDATA[<p>Here are the slides from my talk <a href="http://www.percona.com/live/london-2011/session/programmatic-queries-things-you-can-code-with-sql/">Programmatic Queries: things you can code with SQL</a> held on October 25th on the <a href="http://www.percona.com/live/london-2011/">Percona Live</a> event, London.</p>
<blockquote><p><a href="http://code.openark.org/blog/wp-content/uploads/2011/10/programmatic_queries__things_you_can_code_with_sql.pdf">Programmatic Queries: PDF</a></p></blockquote>
<p>I wish to thank those who attended my talk.</p>
<p>The topic of the talk was irregular and, to some extent, controversial. Should one really rely on internal implementation for optimizing her queries? <em>Sergei Golubchik</em> was quick to suggest that even in current and coming versions of MariaDB, some things I spoke about may not hold true. I accept.</p>
<p>I was in urge to complete my talk within the time frame. I was happy to hear later on that my talk was well received.</p>
<p>There were homework to my talk. I thought I would make some contest picking the best answers, stay tuned.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/slides-from-my-talk-programmatic-queries-things-you-can-code-with-sql/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Speaking on Percona Live, London: &quot;Programmatic Queries: things you can code with SQL&quot;</title>
		<link>http://code.openark.org/blog/mysql/speaking-on-percona-live-london-programmatic-queries-things-you-can-code-with-sql</link>
		<comments>http://code.openark.org/blog/mysql/speaking-on-percona-live-london-programmatic-queries-things-you-can-code-with-sql#comments</comments>
		<pubDate>Mon, 10 Oct 2011 05:48:10 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Execution plan]]></category>
		<category><![CDATA[Speaking]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=4043</guid>
		<description><![CDATA[I'll be speaking at the Percona Live event, held in London, October 24, 25, 2011. My session is called Programmatic Queries: things you can code with SQL. It's a short 30 minute talk, in which I present underlying knowledge of the programmatic nature of SQL queries within MySQL, and how to take advantage of such [...]]]></description>
			<content:encoded><![CDATA[<p>I'll be speaking at the <a href="http://www.percona.com/live/london-2011/">Percona Live</a> event, held in London, October <strong>24, 25, 2011</strong>.</p>
<p>My session is called <a href="http://www.percona.com/live/london-2011/session/programmatic-queries-things-you-can-code-with-sql/">Programmatic Queries: things you can code with SQL</a>. It's a short <strong>30</strong> minute talk, in which I present underlying knowledge of the programmatic nature of SQL queries within MySQL, and how to take advantage of such knowledge so as to build faster, shorter, and sometimes unexpected queries.</p>
<p>This is <em>not</em> about stored routine programming, a classic programmatic aspect of MySQL, but rather about expected order of execution: of row evaluation, of control flow statements, of table inference, of time issues.</p>
<p>I have far too many examples, some real-world problem solvers, and some less common in daily use, to be able to deliver them all on this session. I will pick up those which seem most interesting to me, or those best presenting the programmatic nature of the query. As time allows I may add more examples, or look into interesting future possibilities.</p>
<p>I hope to see you there.</p>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/speaking-on-percona-live-london-programmatic-queries-things-you-can-code-with-sql/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Three wishes for a new year</title>
		<link>http://code.openark.org/blog/mysql/three-wishes-for-a-new-year-2</link>
		<comments>http://code.openark.org/blog/mysql/three-wishes-for-a-new-year-2#comments</comments>
		<pubDate>Tue, 27 Sep 2011 07:39:23 +0000</pubDate>
		<dc:creator>shlomi</dc:creator>
				<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://code.openark.org/blog/?p=3996</guid>
		<description><![CDATA[It's another new year by Jewish calendar. And what do I wish for in the following year? World peace Good health to all Have some way to turn SHOW commands into SELECT statements, server side. I'm fervently trying to hack around this. Stored routines, export/import from file, text manipulation, I don't care! I want to [...]]]></description>
			<content:encoded><![CDATA[<div>
<p>It's another new year by Jewish calendar. And what do I wish for in the following year?</p>
<ol>
<li>World peace</li>
<li>Good health to all</li>
<li>Have <em>some</em> way to turn <strong>SHOW</strong> commands into <strong>SELECT</strong> statements, server side. I'm fervently trying to hack around this. Stored routines, export/import from file, text manipulation, I don't care! I want to <strong>SELECT seconds_behind_master somehow</strong>. Without plugins.</li>
</ol>
<p>PS, none of my <a href="http://code.openark.org/blog/mysql/three-wishes-for-a-new-year">last year's wishes</a> came true. I'll settle for two out of three.</p>
</div>
]]></content:encoded>
			<wfw:commentRss>http://code.openark.org/blog/mysql/three-wishes-for-a-new-year-2/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		</item>
	</channel>
</rss>

