<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/atom10full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:openSearch="http://a9.com/-/spec/opensearch/1.1/" xmlns:georss="http://www.georss.org/georss" xmlns:gd="http://schemas.google.com/g/2005" xmlns:thr="http://purl.org/syndication/thread/1.0" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" gd:etag="W/&quot;CUUHQXgzeCp7ImA9WhVUE0k.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737</id><updated>2012-05-18T05:13:50.680-07:00</updated><title>Where the flamingcow roams</title><subtitle type="html" /><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://flamingcow.dilian.org/" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>23</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/atom+xml" href="http://feeds.feedburner.com/WhereTheFlamingcowRoams" /><feedburner:info uri="wheretheflamingcowroams" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><entry gd:etag="W/&quot;CUADSHk6fip7ImA9WhVUE0w.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-5363638865090326621</id><published>2012-05-17T21:00:00.000-07:00</published><updated>2012-05-17T21:02:59.716-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-05-17T21:02:59.716-07:00</app:edited><title>Fun Python question</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;div&gt;What does this do?&lt;/div&gt;&lt;pre&gt;def func():
&amp;nbsp; print 'foo'
&amp;nbsp; return
&amp;nbsp; yield 'bar'

print func()&lt;/pre&gt;&lt;div&gt;Take a guess, then give it a try.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-5363638865090326621?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/vc2zT9mO4Ylky-6okDiE8xBN5_c/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vc2zT9mO4Ylky-6okDiE8xBN5_c/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/vc2zT9mO4Ylky-6okDiE8xBN5_c/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/vc2zT9mO4Ylky-6okDiE8xBN5_c/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/HwZ4Qk28TIs" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/5363638865090326621/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=5363638865090326621" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/5363638865090326621?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/5363638865090326621?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/HwZ4Qk28TIs/fun-python-question.html" title="Fun Python question" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2012/05/fun-python-question.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DkUMRXo4eCp7ImA9WhVSE04.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-3377742174206555265</id><published>2012-03-09T14:56:00.000-08:00</published><updated>2012-03-09T15:04:44.430-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2012-03-09T15:04:44.430-08:00</app:edited><title>Google MySQL team is hiring</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;&lt;span style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px; text-align: -webkit-auto;"&gt;Do you know MySQL inside and out? Do you have experience running it production? Have you dared to look at the code? Maybe even patched it? Google's MySQL team would love to speak to you. We're hiring several software engineers in Mountain View, CA, USA to primarily work on MySQL server improvements, contributing to Google's &lt;a href="http://code.google.com/p/google-mysql/"&gt;open source MySQL branch&lt;/a&gt;&lt;/span&gt;&lt;span style="background-color: rgba(255, 255, 255, 0.917969); color: #222222; font-family: arial, sans-serif; font-size: 13px; text-align: -webkit-auto;"&gt;. In addition to feature work, Google MySQL developers work closely with operations-focused engineers tracking down bugs and solving tricky performance problems, at truly enormous scale.&lt;br /&gt;
&lt;br /&gt;
Sound interesting? Email&amp;nbsp;&lt;a href="mailto:flamingcow@google.com" style="color: #1155cc;" target="_blank"&gt;flamingcow@google.com&lt;/a&gt;.&lt;/span&gt;&lt;br /&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-3377742174206555265?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/A0-y_sx4Vrl4EHNR-U73WMl6EOw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/A0-y_sx4Vrl4EHNR-U73WMl6EOw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/A0-y_sx4Vrl4EHNR-U73WMl6EOw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/A0-y_sx4Vrl4EHNR-U73WMl6EOw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/hbmiG7f6URg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/3377742174206555265/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=3377742174206555265" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/3377742174206555265?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/3377742174206555265?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/hbmiG7f6URg/google-mysql-team-is-hiring.html" title="Google MySQL team is hiring" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2012/03/google-mysql-team-is-hiring.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A0MAQH84cCp7ImA9WhRQFEs.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-177917185142003839</id><published>2011-12-09T11:48:00.001-08:00</published><updated>2011-12-09T14:24:01.138-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-12-09T14:24:01.138-08:00</app:edited><title>The dangers of max_connections</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
We have a database that's drastically scaling up its query rate from many different clients. This typically means more client jobs and more parallelization across connections, so the first limit we hit is max_user_connections (in the mysql.user table), which we use to provide isolation between runaway users/jobs. We increase that, and we eventually start hitting server-level max_connection limits. We increased that in an emergency push last night, and several hours later performance fell off a cliff.&lt;br /&gt;
&lt;br /&gt;
SHOW PROCESSLIST showed tons of processes in "Opening tables" and "closing tables" state. Our InnoDB IO stats had dropped dramatically; we clearly weren't making significant progress actually answering queries. A quick search turned up a &lt;a href="http://www.mysqlperformanceblog.com/2006/11/21/opening-tables-scalability/"&gt;Percona post&lt;/a&gt; about this, which pointed to &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/table-cache.html"&gt;table_cache&lt;/a&gt;. A quick look at SHOW VARIABLES LIKE 'table_cache' showed 91. Our config has this set to 2048; something had clearly gone wrong.&lt;br /&gt;
&lt;br /&gt;
One hint was the error log message:&lt;br /&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;111209 11:08:21 [Warning] Changed limits: max_open_files: 8192 &amp;nbsp;max_connections: 8000 &amp;nbsp;table_cache: 91&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
It turns out that MySQL tries to be smart about table_cache, based on the open file rlimit. The formula is (max_open_files - max_connections - 10) / 2, which in this case is (8192 - 8000 - 10) = 182 / 2 = 91. 91 active tables is smaller than the hot set in this database, and when query rate crossed a line, the global open/close table lock and underlying syscalls couldn't keep up, and performance death-spiraled from there. We run-time set the limit higher with:&lt;/div&gt;
&lt;div&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;SET GLOBAL table_cache = 2048;&lt;/span&gt;&lt;/div&gt;
&lt;div&gt;
This overrides the automatic setting but opens the possibility of hitting the rlimit when opening tables. The real fix is to increase the rlimit to&amp;nbsp;accommodate&amp;nbsp;both pools of file descriptors.&lt;/div&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-177917185142003839?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/JHcGlcY7zlOnkbI3aOGl7-1anYY/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JHcGlcY7zlOnkbI3aOGl7-1anYY/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/JHcGlcY7zlOnkbI3aOGl7-1anYY/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/JHcGlcY7zlOnkbI3aOGl7-1anYY/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/hg6fFy04iU4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/177917185142003839/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=177917185142003839" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/177917185142003839?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/177917185142003839?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/hg6fFy04iU4/dangers-of-maxconnections.html" title="The dangers of max_connections" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2011/12/dangers-of-maxconnections.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CUENRH89cCp7ImA9WhRRFk0.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-5432589509608355552</id><published>2011-11-29T13:50:00.001-08:00</published><updated>2011-11-29T13:54:55.168-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-29T13:54:55.168-08:00</app:edited><title>Converting subselects to joins, part 2</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
&lt;a href="http://flamingcow.dilian.org/2011/07/converting-subselects-to-joins.html"&gt;I previously discussed this in depth&lt;/a&gt;. However, today I saw a case that I didn't cover:&lt;br /&gt;
&lt;br /&gt;
You have a table of Users and a table of Logins, with a row for each user login event. You're looking for users that have logged in within the last 31 days. The initial version of this I saw used a derived table:&lt;br /&gt;
&lt;pre&gt;SELECT
    UserId,
    LastLogin
  FROM Users
    JOIN (
      SELECT
          UserId,
          DATEDIFF(NOW(), MAX(TimeStamp)) AS LastLogin
        FROM Logins
        GROUP BY UserId
    ) AS Temp USING (UserId)
  WHERE LastLogin &amp;lt;= 31;&lt;/pre&gt;
We can convert this to a simple JOIN with the magic of HAVING. HAVING is like WHERE, but applies after aggregation:&lt;br /&gt;
&lt;pre&gt;SELECT
    UserId,
    DATEDIFF(NOW(), MAX(TimeStamp)) AS LastLogin
  FROM Users
    JOIN Logins USING (UserId)
  GROUP BY UserId
  HAVING LastLogin &amp;lt;= 31;&lt;/pre&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-5432589509608355552?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/tXWltLE9AoUlulU916Vj8cCY5Fk/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tXWltLE9AoUlulU916Vj8cCY5Fk/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/tXWltLE9AoUlulU916Vj8cCY5Fk/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/tXWltLE9AoUlulU916Vj8cCY5Fk/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/pk-2ObC_CEw" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/5432589509608355552/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=5432589509608355552" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/5432589509608355552?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/5432589509608355552?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/pk-2ObC_CEw/converting-subselects-to-joins-part-2.html" title="Converting subselects to joins, part 2" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2011/11/converting-subselects-to-joins-part-2.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEUNR30-fip7ImA9WhRRFk0.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-3046326960109772008</id><published>2011-11-29T12:48:00.001-08:00</published><updated>2011-11-29T13:31:36.356-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-11-29T13:31:36.356-08:00</app:edited><title>Safe(r) data changes</title><content type="html">&lt;div dir="ltr" style="text-align: left;" trbidi="on"&gt;
It's a great goal to avoid making manual changes to your database. It never works 100%, though; there are always software bugs, unexpected interactions and other events that muck up your data, and you have to do one-off corrections. These are inherently hazardous: hard to test for unexpected data corruption, hard to apply consistently and hard to model the application behavior that results from them. Here are some strategies for the first issue, avoiding unexpected data corruption.&lt;br /&gt;
&lt;ol style="text-align: left;"&gt;
&lt;li&gt;Don't run one-off executables against your database. Instead, have the executable print out SQL that it would have run to update the database. If something goes wrong, you don't have to model the behavior of the program; you can just look at the SQL.&lt;/li&gt;
&lt;li&gt;Check the SQL files into source control somewhere. Manual changes tend to breed more manual changes to fix the fixes, so you never know when you'll want a record of what you twiddled in the past.&lt;/li&gt;
&lt;li&gt;Include all fields from the primary key in the WHERE clause. This ensures that each statement only modifies one row. Even if this results in a huge list of changes, at least you know exactly what changed.&lt;/li&gt;
&lt;li&gt;Include as many additional gating clauses as possible, linked with AND. For example, if you have a table of products and you want to set the price to 0.99 for everything that is currently set to 1.00, do:&lt;br /&gt;
&lt;span style="font-family: 'Courier New', Courier, monospace;"&gt;UPDATE Products SET Price=0.99 WHERE ProductId=2762 AND Price=1.00;&lt;/span&gt;&lt;br /&gt;
&lt;span style="font-family: inherit;"&gt;This ensures that if something else changes Price just before you run your change, you don't destroy that update.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;&lt;span style="font-family: inherit;"&gt;Record the number of rows affected by each statement, in case something unexpected happens.&lt;/span&gt;&lt;/li&gt;
&lt;li&gt;Use transactions sensibly. Overly huge grouping of statements can block replication, but consider whether your changes will be toxic if partially applied.&lt;/li&gt;
&lt;li&gt;Stop running changes on errors or warnings and let a human examine the output. Warnings like string truncation can be a sign of a broken change.&lt;/li&gt;
&lt;/ol&gt;
&lt;div&gt;
#4 can be a challenge if your verification statements are complex. Consider, for example, if you want to update rows in table A for which there is exactly one row for a particular CustomerId. It's relatively easy to do a SELECT statement to verify this by hand:&lt;/div&gt;
&lt;pre&gt;SELECT
    CustomerId,
    COUNT(CustomerId)
  FROM A
  WHERE
    CustomerId IN (15, 16)
  GROUP BY CustomerId;
&lt;/pre&gt;
&lt;div&gt;
To verify this at UPDATE time, however, you either need a subselect or an intermediate table. We'll use the latter:&lt;/div&gt;
&lt;pre&gt;CREATE TABLE ScratchTable AS
  SELECT
      CustomerId,
      COUNT(CustomerId) AS Customers
    FROM A
    WHERE
      CustomerId IN (15, 16)
    GROUP BY CustomerId;

UPDATE A
  JOIN ScratchTable USING (CustomerId)
  SET Updated=1
  WHERE
    A.Id=3
    AND Customers=1;
&lt;/pre&gt;
&lt;div&gt;
&lt;span style="font-family: inherit;"&gt;The same trick works if your data change inserts new rows:&lt;/span&gt;&lt;/div&gt;
&lt;pre&gt;INSERT INTO A (CustomerId)
  SELECT CustomerId
    FROM ScratchTable
    WHERE
      CustomerId=15
      AND Customers=1;
&lt;/pre&gt;
&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-3046326960109772008?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/08n-HxHb-pUXBNWtCj-cIYKLg8Q/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/08n-HxHb-pUXBNWtCj-cIYKLg8Q/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/08n-HxHb-pUXBNWtCj-cIYKLg8Q/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/08n-HxHb-pUXBNWtCj-cIYKLg8Q/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/i1zfENXu-Rc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/3046326960109772008/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=3046326960109772008" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/3046326960109772008?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/3046326960109772008?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/i1zfENXu-Rc/safer-data-changes.html" title="Safe(r) data changes" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2011/11/safer-data-changes.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Dk8MQ3w-cCp7ImA9WhdRGU8.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-5724799282572905278</id><published>2011-08-09T14:03:00.001-07:00</published><updated>2011-08-09T14:21:22.258-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-09T14:21:22.258-07:00</app:edited><title>InnoDB as the default table type</title><content type="html">We recently switched from MyISAM to InnoDB as the default table type. This affects CREATE TABLE without an explicit ENGINE=, as well as implicitly-created tables for sorting and such. Mark had previously discussed issues with this &lt;a href="http://mysqlha.blogspot.com/2009/06/what-could-possibly-go-wrong.html"&gt;here&lt;/a&gt;, but we thought it was worth giving another try.
&lt;br /&gt;
&lt;br /&gt;We've found a far more basic problem: KILL takes a long time. Consider the following:
&lt;br /&gt;&lt;tt&gt;CREATE TABLE scratch.MyShortLivedTable
&lt;br /&gt;&amp;nbsp;&amp;nbsp;SELECT * FROM A JOIN B JOIN C....;&lt;/tt&gt;
&lt;br /&gt;There's no ENGINE= there, so it uses the default table type. It seems to run at about the same speed as it did with MyISAM, but then you kill it. If it's MyISAM, the KILL takes effect immediately. If it's InnoDB, the CREATE is non-transactional and stays, but the implicit INSERTs have to be rolled back. If that query took 10 minutes, it may take 10 minutes to roll back, during which time the query is unkillable and MySQL won't shut down cleanly.
&lt;br /&gt;
&lt;br /&gt;Our failovers rely on being able to kill all connections to a slave that they're promoting to master. Our backups rely on being able to shut down MySQL. We don't have a good answer for this, short of hardwiring ENGINE=MyISAM onto writes we know are going to be large.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-5724799282572905278?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QkIO1TqwsoOMse2ZK5lJy4WaCn4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QkIO1TqwsoOMse2ZK5lJy4WaCn4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QkIO1TqwsoOMse2ZK5lJy4WaCn4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QkIO1TqwsoOMse2ZK5lJy4WaCn4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/5TEZw4CV-G0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/5724799282572905278/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=5724799282572905278" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/5724799282572905278?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/5724799282572905278?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/5TEZw4CV-G0/innodb-as-default-table-type.html" title="InnoDB as the default table type" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2011/08/innodb-as-default-table-type.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0IBRX48eSp7ImA9WhdRGEs.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-7240577218975863504</id><published>2011-08-08T13:33:00.000-07:00</published><updated>2011-08-08T20:45:54.071-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-08-08T20:45:54.071-07:00</app:edited><title>Database best practices for future scalability</title><content type="html">There’s a perpetual debate about how much effort to put into scalability when first designing and building a modern web application. The opposing arguments are roughly: “Scalability doesn’t matter if your app isn’t successful; features should come first” vs. “When you know that you need to scale, you won’t have time to do it.” Below are some suggestions for scalable MySQL schema design that should get you on the right path, without being onerous enough to slow you down. Let’s start with things that are almost free:
&lt;br /&gt;&lt;ol&gt;
&lt;br /&gt;&lt;li&gt;Use InnoDB. You’re eventually likely to want transactions, foreign keys, row-level locking or relative crash safety. You can Google and find lots of InnoDB vs. MyISAM comparisons, but if you don’t want to dig too deeply, “just use InnoDB” is a safe place to start.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Don’t store data that you don’t intend to use relationally. Using MySQL as a key/value store or to store encoded data (XML, &lt;a href="http://code.google.com/p/protobuf/"&gt;protocol buffers&lt;/a&gt;, etc.) in BLOB/TEXT may work, but dedicated key/value stores are likely to be more efficient.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Try to design your schema with as few hierarchies as possible. For example, take the following table layout, with arrows representing many-to-one relationships:&lt;img style="display:block; margin:0px auto 10px; text-align:center;width: 225px; height: 186px;" src="http://2.bp.blogspot.com/-ANuluwrBTBM/TkBK7JNnThI/AAAAAAAAR5E/3V9N8srmFKQ/s320/Databasebestpracticesforfuturescalability.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5638589113413619218" /&gt;Perhaps A=”Users”, B=”DVDs Owned”, C=”Logins”, D=”Times Watched”, while E=”Administrators” and F=”Changes”. These are two hierarchies, since A and E have no links to each other. Minimizing the number of hierarchies (keeping it to just one is awesome!) makes it easier to shard later. Schemas with cross-links (say F also links to A, or a table records transfers between two different users, linking to A twice) are very difficult to shard.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Use BIGINT UNSIGNED NOT NULL (64-bit required numeric) primary keys on every table. AUTO_INCREMENT is fine, at least to start. You can skip this for many-to-many link tables; just put both link columns in the primary key. Having single-column, numeric primary keys makes it easier to do things like drift checking and traversing between tables.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Use BIGINT instead of INT for all keys. The cost in space (4 vs. 8 bytes) and compute time is so small that you’ll never notice it, but the cost of a schema change later to increase the field size, or an accidental wraparound, can be enormous. As you expand shards, your key space becomes sparse and grows rapidly, so wide keys are critical.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Split off your data access code into an &lt;a href="http://en.wikipedia.org/wiki/Object-relational_mapping"&gt;ORM layer&lt;/a&gt;, even if it’s very simple to begin with. This will be where your read/write split, shard lookups and change tracking will live later.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Don't use &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/triggers.html"&gt;triggers&lt;/a&gt; or &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/stored-routines.html"&gt;stored routines&lt;/a&gt;. Keep this logic in your ORM layer instead, to give yourself a single point of truth and versioning system.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;&lt;a href="http://flamingcow.dilian.org/2011/07/converting-subselects-to-joins.html"&gt;Avoid subselects; use joins instead&lt;/a&gt;.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Don’t use &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/views.html"&gt;views&lt;/a&gt;, unless you’re using a third-party ORM (rails, django) that mandates a schema structure that isn’t ideal.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Avoid network round-trips whenever possible. Use the &lt;a href="http://dev.mysql.com/doc/refman/5.5/en/insert.html"&gt;multi-row insert syntax&lt;/a&gt; where possible. Enable the &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/mysql-real-connect.html"&gt;CLIENT_MULTI_STATEMENTS&lt;/a&gt; flag at connect time, then send groups of statements separated by ";".
&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;
&lt;br /&gt;Then, things that cost development time, in increasing order of complexity:
&lt;br /&gt;&lt;ol&gt;&lt;li&gt;Use &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/ansi-diff-foreign-keys.html"&gt;foreign keys&lt;/a&gt;. Don’t make references nullable; use a flag field to mark whole (sub-)hierarchies deleted instead. Combined with the hierarchy rule above, this means that you guarantee yourself that you’ll never end up with orphaned rows.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;&lt;a href="http://dev.mysql.com/doc/refman/5.1/en/replication.html"&gt;Write to masters; read from slaves&lt;/a&gt;. This can be quite complex, since you have to worry about replication delay. For example, you can’t have one web page hit cause a write, then the next hit render the results by reading from the database, because the result might not have replicated. However, this enables significant scaling, because hooking up more slaves is much easier than sharding.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Don’t store event-based data as one row per event. If you record page views or clicks in the database, aggregate that data into one row per hour, or per day. You can keep logs of events outside of the database in case you need to change aggregation and re-generate historical data, but don’t keep every event in a hot table.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Stop using AUTO_INCREMENT. Instead, keep a table &lt;a href="http://www.reddit.com/r/mysql/comments/jcw8o/database_best_practices_for_future_scalability/c2b2o4v"&gt;IdSequences&lt;/a&gt;, and do something like:
&lt;br /&gt;&lt;div style="font-family: monospace"&gt;BEGIN;
&lt;br /&gt;UPDATE IdSequences SET LastId=LAST_INSERT_ID(LastId+Increment)
&lt;br /&gt;&amp;nbsp;&amp;nbsp;WHERE TableName='A' AND ColumnName='b';
&lt;br /&gt;INSERT INTO A (b, c) VALUES (LAST_INSERT_ID(), ‘foo’);
&lt;br /&gt;COMMIT;&lt;/div&gt;This lets you change IdSequences later to modify your sharding scheme.&lt;/li&gt;
&lt;br /&gt;&lt;li&gt;Create an empty shard (new database, same schema, no data) and add test rows. Teach your application to choose which shard to talk to. This will require some method to look up a shard for the root of each hierarchy; keep all data linked to a particular root on the same shard, so you can JOIN it. At its simplest, the lookup can be (ID mod NumShards). If you have uneven shard growth, you may need an indirection table to map from virtual shard (determined by modular division with a large divisor) to physical database.&lt;/li&gt;&lt;/ol&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-7240577218975863504?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/j0QXd5HUT9SLt18Fp3elAUdbTrg/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/j0QXd5HUT9SLt18Fp3elAUdbTrg/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/j0QXd5HUT9SLt18Fp3elAUdbTrg/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/j0QXd5HUT9SLt18Fp3elAUdbTrg/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/jXVh5uR6OFA" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/7240577218975863504/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=7240577218975863504" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/7240577218975863504?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/7240577218975863504?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/jXVh5uR6OFA/database-best-practices-for-future.html" title="Database best practices for future scalability" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/-ANuluwrBTBM/TkBK7JNnThI/AAAAAAAAR5E/3V9N8srmFKQ/s72-c/Databasebestpracticesforfuturescalability.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2011/08/database-best-practices-for-future.html</feedburner:origLink></entry><entry gd:etag="W/&quot;A08GRX0_fip7ImA9WhdTFU0.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-6511616893203975736</id><published>2011-07-12T14:03:00.000-07:00</published><updated>2011-07-12T15:30:24.346-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-07-12T15:30:24.346-07:00</app:edited><title>Converting subselects to joins</title><content type="html">&lt;div&gt;&lt;pre&gt;mysql&amp;gt; SELECT Title&lt;br /&gt;    -&amp;gt;   FROM Articles&lt;br /&gt;    -&amp;gt;   WHERE ArticleId IN (&lt;br /&gt;    -&amp;gt;     SELECT ArticleId&lt;br /&gt;    -&amp;gt;     FROM Views&lt;br /&gt;    -&amp;gt;   );&lt;br /&gt;+-------------------------+&lt;br /&gt;| Title                   |&lt;br /&gt;+-------------------------+&lt;br /&gt;| Interesting things      |&lt;br /&gt;| More interesting things |&lt;br /&gt;+-------------------------+&lt;br /&gt;2 rows in set (0.00 sec)&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;What's wrong with this statement? It looks like it's trying to get a list of article names that have been viewed, and it seems to be doing its job. It's easy to read and to tell what's going on, even for someone with limited SQL experience. So what's there to fix?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;Notice that there are two SELECT statements above. The latter is called a subselect or subquery. Just like parentheses in mathematical expressions ("5 * (2 + 8)"), you're walling off part of your statement and asking for it to be completely executed first. If that inner statement produces a huge data set (imagine this is views of, say, reddit articles), it's bad if you have to store that entire result before moving on to finding the associated articles. In reality, database engines can optimize this and be smarter than storing the whole result set, but there are no guarantees.&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"&gt;Fortunately, most subselects can be converted directly to joins. Let's look at a few simple examples. Given the tables:&lt;br /&gt;&lt;pre&gt;CREATE TABLE Articles (&lt;br /&gt;  ArticleId bigint(20) unsigned NOT NULL AUTO_INCREMENT,&lt;br /&gt;  Title varchar(255) NOT NULL,&lt;br /&gt;  PRIMARY KEY (ArticleId)&lt;br /&gt;) ENGINE=InnoDB;&lt;br /&gt;&lt;br /&gt;CREATE TABLE Views (&lt;br /&gt;  ArticleId bigint(20) unsigned NOT NULL,&lt;br /&gt;  ViewedAt timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,&lt;br /&gt;  KEY ArticleId (ArticleId),&lt;br /&gt;  CONSTRAINT Views_ibfk_1 FOREIGN KEY (ArticleId) REFERENCES Articles (ArticleId)&lt;br /&gt;) ENGINE=InnoDB;&lt;/pre&gt;We'll start with a simple query:&lt;br /&gt;&lt;pre&gt;SELECT Title&lt;br /&gt;  FROM Articles&lt;br /&gt;  WHERE ArticleId IN (&lt;br /&gt;    SELECT ArticleId&lt;br /&gt;    FROM Views&lt;br /&gt;  );&lt;/pre&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;This is easy because it's a positive relationship: "IN" as opposed to "NOT IN". As a join, it looks like:&lt;br /&gt;&lt;pre&gt;SELECT DISTINCT Title&lt;br /&gt;  FROM Articles&lt;br /&gt;    JOIN Views USING (ArticleId);&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;"DISTINCT" is required because Views -&amp;gt; Articles is many -&amp;gt; one, and we only want each article title once. We can use "USING" instead of "ON" because the column name is the same in both tables.&lt;/div&gt;&lt;div&gt;So, what if we have a negative query? Say we're looking for unviewed articles:&lt;br /&gt;&lt;pre&gt;SELECT Title&lt;br /&gt;  FROM Articles&lt;br /&gt;  WHERE ArticleId NOT IN (&lt;br /&gt;    SELECT ArticleId&lt;br /&gt;    FROM Views&lt;br /&gt;  );&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;We can turn this into a join by using something called an &lt;a href="http://en.wikipedia.org/wiki/Join_(SQL)#Outer_joins"&gt;outer join&lt;/a&gt;. Outer joins give us back all the rows in one table, then matching rows from another, or NULLs if they don't exist. An outer join between these two tables would look like:&lt;pre&gt;mysql&amp;gt; SELECT Title, ViewedAt&lt;br /&gt;    -&amp;gt;   FROM Articles&lt;br /&gt;    -&amp;gt;     LEFT JOIN Views USING (ArticleId);&lt;br /&gt;+-------------------------+---------------------+&lt;br /&gt;| Title                   | ViewedAt            |&lt;br /&gt;+-------------------------+---------------------+&lt;br /&gt;| Interesting things      | 2011-07-12 14:09:28 |&lt;br /&gt;| More interesting things | 2011-07-12 14:09:29 |&lt;br /&gt;| More interesting things | 2011-07-12 14:09:31 |&lt;br /&gt;| Rather boring things    |                NULL |&lt;br /&gt;+-------------------------+---------------------+&lt;br /&gt;4 rows in set (0.00 sec)&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;We can then filter back down to just unread articles. We'll also avoid referencing any columns but the ones we're already joining on:&lt;br /&gt;&lt;pre&gt;mysql&amp;gt; SELECT Title&lt;br /&gt;    -&amp;gt;   FROM Articles&lt;br /&gt;    -&amp;gt;     LEFT JOIN Views USING (ArticleId)&lt;br /&gt;    -&amp;gt;   WHERE Views.ArticleId IS NULL;&lt;br /&gt;+----------------------+&lt;br /&gt;| Title                |&lt;br /&gt;+----------------------+&lt;br /&gt;| Rather boring things |&lt;br /&gt;+----------------------+&lt;br /&gt;1 row in set (0.00 sec)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;Take an example query that is looking for all articles that have not been read since a certain timestamp:&lt;br /&gt;&lt;pre&gt;mysql&amp;gt; SELECT Title&lt;br /&gt;    -&amp;gt;   FROM Articles&lt;br /&gt;    -&amp;gt;   WHERE ArticleId NOT IN (&lt;br /&gt;    -&amp;gt;     SELECT ArticleId&lt;br /&gt;    -&amp;gt;       FROM Views&lt;br /&gt;    -&amp;gt;       WHERE ViewedAt &amp;gt; '2011-07-12 14:09:30'&lt;br /&gt;    -&amp;gt;   );&lt;br /&gt;+----------------------+&lt;br /&gt;| Title                |&lt;br /&gt;+----------------------+&lt;br /&gt;| Interesting things   |&lt;br /&gt;| Rather boring things |&lt;br /&gt;+----------------------+&lt;br /&gt;2 rows in set (0.00 sec)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;This is slightly more complex to convert, because the naive conversion returns the wrong answer:&lt;br /&gt;&lt;pre&gt;mysql&amp;gt; SELECT Title&lt;br /&gt;    -&amp;gt;   FROM Articles&lt;br /&gt;    -&amp;gt;     LEFT JOIN Views USING (ArticleId)&lt;br /&gt;    -&amp;gt;   WHERE ViewedAt &amp;gt; '2011-07-12 14:09:30'&lt;br /&gt;    -&amp;gt;     AND Views.ArticleId IS NULL;&lt;br /&gt;Empty set (0.00 sec)&lt;br /&gt;&lt;/pre&gt;&lt;/div&gt;&lt;div&gt;To solve this, we have to remember that we want the ViewedAt condition to be &lt;i&gt;before&lt;/i&gt; the join, while the Views.ArticleId condition should be &lt;i&gt;after&lt;/i&gt;. We can rewrite this to:&lt;br /&gt;&lt;pre&gt;mysql&amp;gt; SELECT Title&lt;br /&gt;    -&amp;gt;   FROM Articles&lt;br /&gt;    -&amp;gt;     LEFT JOIN Views ON (Articles.ArticleId = Views.ArticleId&lt;br /&gt;    -&amp;gt;                         AND ViewedAt &amp;gt; '2011-07-12 14:09:30')&lt;br /&gt;    -&amp;gt;   WHERE Views.ArticleId IS NULL;&lt;br /&gt;+----------------------+&lt;br /&gt;| Title                |&lt;br /&gt;+----------------------+&lt;br /&gt;| Interesting things   |&lt;br /&gt;| Rather boring things |&lt;br /&gt;+----------------------+&lt;br /&gt;2 rows in set (0.00 sec)&lt;/pre&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-6511616893203975736?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/rgYfLZVkt8O4K24s-gvMHAuxuCo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rgYfLZVkt8O4K24s-gvMHAuxuCo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/rgYfLZVkt8O4K24s-gvMHAuxuCo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/rgYfLZVkt8O4K24s-gvMHAuxuCo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/jqYziOlB_qg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/6511616893203975736/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=6511616893203975736" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6511616893203975736?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6511616893203975736?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/jqYziOlB_qg/converting-subselects-to-joins.html" title="Converting subselects to joins" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2011/07/converting-subselects-to-joins.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAARXozcCp7ImA9WhZWFUo.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-6004374994407586232</id><published>2011-05-16T12:14:00.000-07:00</published><updated>2011-05-16T13:45:44.488-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-05-16T13:45:44.488-07:00</app:edited><title>Paris</title><content type="html">&lt;div style="text-align: left;"&gt;I'm on a two-week trip to Dublin for work and decided to break it up with a trip to a city that I'd never been closer to than the airport: Paris. Luckily, I have a French-speaking friend who's great company, so off we went.&lt;/div&gt;&lt;div&gt;As the airfare to Dublin was covered by Google, I decided to splurge a bit on Paris. We ended up staying at the &lt;a href="http://www.raphael-hotel.com/"&gt;Hotel Raphael&lt;/a&gt;, which was excellent throughout. It's beautiful, if a bit overwhelming for modern tastes. Having a great concierge and a room with everything at hand, however, makes a world of difference. Also, a balcony with a view of the Eiffel Tower: awesome.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; "&gt;&lt;img src="http://michaelromei.files.wordpress.com/2010/12/galerie12.jpg" border="0" alt="" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 600px; height: 400px; " /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Morgan arrived later than I did on Friday, so I ended up venturing out on my own to a restaurant with concierge directions and the ability to speak about 3 words of French. I ended up at &lt;a href="http://www.restaurant-jamin.com/"&gt;Jamin&lt;/a&gt; for my first taste of real French food. Lesson #1: no one orders wine by the glass. Lesson #2: holy shit, this is good! French has never been my favorite genre for restaurants in the US, but this was amazing.&lt;/div&gt;&lt;div&gt;Morgan arrived around midnight, and after figuring out the horribly baroque lighting system in the hotel room, we turned in and got up early. We went first to the &lt;a href="http://en.wikipedia.org/wiki/Jardin_des_Plantes"&gt;Jardin des Plantes&lt;/a&gt;, which is beautiful if a bit ill-cared-for. The menagerie is actually better kept than the botanical gardens, probably because it attracts a bigger crowd. If you go, do visit the greenhouses though.&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.parisiensalon.com/wp-content/uploads/2009/10/jardin-des-plantes.jpeg" onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}"&gt;&lt;img src="http://www.parisiensalon.com/wp-content/uploads/2009/10/jardin-des-plantes.jpeg" border="0" alt="" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 600px; height: 399px; " /&gt;&lt;/a&gt;&lt;div style="text-align: left;"&gt;We ate lunch looking out at &lt;a href="http://en.wikipedia.org/wiki/Notre_Dame_de_Paris"&gt;Notre Dame Cathedral&lt;/a&gt;, then walked around it. The line was too long and we didn't head in. Instead, we headed up to &lt;a href="http://en.wikipedia.org/wiki/Basilique_du_Sacr%C3%A9-C%C5%93ur,_Paris"&gt;Sacré-Cœur&lt;/a&gt;, with its amazing panoramic view of Paris. We stepped inside, but weren't terribly enthused; I don't think either of us is really a church person, even architecturally.&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; "&gt;&lt;img src="http://upload.wikimedia.org/wikipedia/en/thumb/f/f0/Skyline_Sacre_Cour.jpg/1300px-Skyline_Sacre_Cour.jpg" border="0" alt="" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 600px; " /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Of course, you can't go to Paris for the first time and not see the Eiffel Tower. Again we didn't go in/up because of the throng, but it's still impressive to see.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; "&gt;&lt;img src="http://farm3.static.flickr.com/2610/3681355338_d8083b6e35.jpg" border="0" alt="" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 500px; height: 315px; " /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Then we were back to the hotel to clean up and change, and off to dinner with a quick stop at the rooftop bar.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; "&gt;&lt;img src="http://media.expedia.com/hotels/1000000/30000/28600/28507/28507_117_b.jpg" border="0" alt="" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 346px; height: 288px; " /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;We had dinner reservations at &lt;a href="http://www.paris-best-restaurants.com/top.php/restaurant-victor-paris-restaurant/zi108570"&gt;Restaurant Victor&lt;/a&gt;, described by the concierge as a "bistro"; Morgan scoffed. We arrived, the food arrived, Morgan no longer scoffed. I had an appetizer of morel mushrooms in cream sauce that I will remember for quite some time.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; "&gt;&lt;img src="http://www.paris-best-restaurants.com/img/items/victor-restaurant-paris.jpg" border="0" alt="" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 250px; height: 250px; " /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;The next morning, we checked out and headed off to a tiny, unassuming building that marks the entrance to the &lt;a href="http://en.wikipedia.org/wiki/Catacombs_of_Paris"&gt;Catacombs of Paris&lt;/a&gt;. Down a long staircase, though long, small tunnels, and then past the bones of 6 million former Parisians artfully arranged. The experience is surreal; while there are plenty of pictures online, the sheer scale of the thing in person is stunning. It seems to go on and back forever. What's also stunning is something that would never happen in the US: the only things separating you from the walls of bones are signs are signs reminding you not to touch.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; "&gt;&lt;img src="http://8th-grade-english.wikispaces.com/file/view/paris-catacombs-2-wall-of-bones.jpg/51356611/paris-catacombs-2-wall-of-bones.jpg" border="0" alt="" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 500px; height: 403px; " /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;After emerging into the sunlight slightly stunned, we took a quick trip to see the Louvre from the outside, then the hotel to pick up bags and off in our respective directions. I think I'll be headed back to Paris for a longer stay in the future. I seem to enjoy it very much.&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 238); -webkit-text-decorations-in-effect: underline; "&gt;&lt;img src="http://www.visitingdc.com/images/louvre-museum-picture.jpg" border="0" alt="" style="display: block; margin-top: 0px; margin-right: auto; margin-bottom: 10px; margin-left: auto; text-align: center; cursor: pointer; width: 625px; height: 401px; " /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-6004374994407586232?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/7OKavc572Q1u00gZ_zoSuJDOBaE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7OKavc572Q1u00gZ_zoSuJDOBaE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/7OKavc572Q1u00gZ_zoSuJDOBaE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/7OKavc572Q1u00gZ_zoSuJDOBaE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/DwsgHG2ejFg" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/6004374994407586232/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=6004374994407586232" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6004374994407586232?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6004374994407586232?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/DwsgHG2ejFg/paris.html" title="Paris" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://farm3.static.flickr.com/2610/3681355338_d8083b6e35_t.jpg" height="72" width="72" /><thr:total>1</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2011/05/paris.html</feedburner:origLink></entry><entry gd:etag="W/&quot;C0ACQXk_fip7ImA9WhZQFUw.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-2591955205341255509</id><published>2011-04-22T15:30:00.001-07:00</published><updated>2011-04-22T15:36:00.746-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-22T15:36:00.746-07:00</app:edited><title>Avoid MySQL round trips</title><content type="html">100ms (e.g. cross-US) latency to your MySQL server? Running 100,000 statements? That's 3 hours of overhead before you even get to your statement runtime on the server. Quick hack:&lt;br /&gt;&lt;pre&gt;mysql&amp;gt; delimiter |&lt;br /&gt;mysql&amp;gt; select 1;&lt;br /&gt; -&amp;gt; select 2;&lt;br /&gt; -&amp;gt; |&lt;br /&gt;+---+&lt;br /&gt;| 1 |&lt;br /&gt;+---+&lt;br /&gt;| 1 |&lt;br /&gt;+---+&lt;br /&gt;1 row in set (0.00 sec)&lt;br /&gt;&lt;br /&gt;+---+&lt;br /&gt;| 2 |&lt;br /&gt;+---+&lt;br /&gt;| 2 |&lt;br /&gt;+---+&lt;br /&gt;1 row in set (0.00 sec)&lt;br /&gt;&lt;/pre&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-2591955205341255509?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/P9UZPwcMX8l1YcUCmZv5Uc1YqxQ/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/P9UZPwcMX8l1YcUCmZv5Uc1YqxQ/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/P9UZPwcMX8l1YcUCmZv5Uc1YqxQ/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/P9UZPwcMX8l1YcUCmZv5Uc1YqxQ/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/tdHvKJ_v3dY" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/2591955205341255509/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=2591955205341255509" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/2591955205341255509?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/2591955205341255509?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/tdHvKJ_v3dY/avoid-mysql-round-trips.html" title="Avoid MySQL round trips" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2011/04/avoid-mysql-round-trips.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CU4DQXYzeip7ImA9WhZQEkk.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-3151672626268125291</id><published>2011-04-19T11:50:00.001-07:00</published><updated>2011-04-19T13:12:50.882-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-19T13:12:50.882-07:00</app:edited><title>Video sharing sucks</title><content type="html">&lt;div&gt;&lt;p&gt;So, I took some friends to &lt;a href="http://iflysfbay.com/"&gt;iFlySFBay&lt;/a&gt; the other evening. We had a great time and they gave us a DVD. It's certainly not the awesomest format to share with your friends, so I used &lt;a href="http://handbrake.fr/"&gt;HandBrake&lt;/a&gt; to rip it to h264. Next up: how do I easily share it?&lt;/p&gt;&lt;p&gt;I started with &lt;a href="https://www.dropbox.com/"&gt;DropBox&lt;/a&gt;. Upload was nice and easy but there's no playback UI; you're stuck with your browser UI, which is pretty lousy in &lt;a href="http://www.google.com/chrome/"&gt;Chrome&lt;/a&gt;, but works: &lt;a href="http://dl.dropbox.com/u/13482590/iFLY.m4v"&gt;http://dl.dropbox.com/u/13482590/iFLY.m4v&lt;/a&gt;&lt;/p&gt;&lt;p&gt;Next up: &lt;a href="https://www.amazon.com/clouddrive/learnmore"&gt;Amazon Cloud Drive&lt;/a&gt;. Hold on, what, no sharing?&lt;/p&gt;&lt;p&gt;Then: &lt;a href="https://picasaweb.google.com/"&gt;PicasaWeb&lt;/a&gt;. 1 GB size limit?!?&lt;/p&gt;&lt;p&gt;OK, I guess I'll fall back to &lt;a href="http://www.youtube.com/"&gt;YouTube&lt;/a&gt;, since they removed the video length limit. "Failed (unable to convert video file)." Chrome can play it but YouTube can't decode it?&lt;/p&gt;&lt;p&gt;&lt;a href="https://www.facebook.com/"&gt;Facebook&lt;/a&gt;: 1 GiB/20 minute limit.&lt;/p&gt;&lt;p&gt;This really should not be a hard problem. It's a compressed version of a 30 minute movie. Why is this so difficult?&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-3151672626268125291?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/QMSgHGrVo8jtiKwg9IK8CdDjw-Q/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QMSgHGrVo8jtiKwg9IK8CdDjw-Q/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/QMSgHGrVo8jtiKwg9IK8CdDjw-Q/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/QMSgHGrVo8jtiKwg9IK8CdDjw-Q/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/6aFN5WpvvOQ" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/3151672626268125291/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=3151672626268125291" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/3151672626268125291?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/3151672626268125291?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/6aFN5WpvvOQ/video-sharing-sucks.html" title="Video sharing sucks" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2011/04/video-sharing-sucks.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUMRH88eyp7ImA9WhZSF00.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-9215033455622445914</id><published>2011-04-01T15:41:00.001-07:00</published><updated>2011-04-01T16:24:45.173-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2011-04-01T16:24:45.173-07:00</app:edited><title>A new generation of Google MySQL tools</title><content type="html">&lt;div&gt;&lt;p&gt;When I started at Google, the MySQL team had a moderate open source presence. The largest part was the Google server patches for 4.0, 5.0 and some starter work on 5.1. There was also a small set of tools: mypgrep, mstat and some others. Chip Turner, who did the tools releases, had already moved to another team, and we haven't released new tools since.&lt;/p&gt;&lt;p&gt;I'm now happy to announce a new round of tool releases. We're just getting started, but here's what's available so far:&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/google-mysql-tools/source/browse/trunk/pylib/db.py"&gt;db.py&lt;/a&gt;: Easily execute queries in parallel on a sharded database&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/google-mysql-tools/source/browse/trunk/sql.py"&gt;sql.py&lt;/a&gt;: Interactive shell to db.py&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/google-mysql-tools/source/browse/trunk/permissions.py"&gt;permissions.py&lt;/a&gt;: Manage MySQL permissions in a Python-based format&lt;/li&gt;&lt;li&gt;&lt;a href="http://code.google.com/p/google-mysql-tools/source/browse/trunk/validate.py"&gt;validate.py&lt;/a&gt;: Parse SQL using pyparsing and apply rules with live DB data&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;These are the actual tools being used to run MySQL at scale inside Google, not one-time sanitized copies. You can get them at &lt;a href="http://code.google.com/p/google-mysql-tools/"&gt;http://code.google.com/p/google-mysql-tools/&lt;/a&gt;. The old tools and patches are still available in &lt;a href="http://code.google.com/p/google-mysql-tools/source/browse/#svn%2Ftrunk%2Fold"&gt;old/&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Thanks to the whole team for their work on these tools and especially to Razvan Musaloiu-E. for handling release code reviews. Watch/subscribe to this blog or subscribe to &lt;a href="http://groups.google.com/group/google-mysql-tools"&gt;the google-mysql-tools mailing list&lt;/a&gt; for future updates. If you'll be at the &lt;a href="http://en.oreilly.com/mysql2011/"&gt;2011 MySQL conference&lt;/a&gt;, stop by my talk with &lt;a href="http://en.oreilly.com/mysql2011/public/schedule/speaker/8129"&gt;Eric Rollins&lt;/a&gt; on &lt;a href="http://en.oreilly.com/mysql2011/public/schedule/detail/17137"&gt;automatic failover&lt;/a&gt; and &lt;a href="http://en.oreilly.com/mysql2011/public/schedule/speaker/57828"&gt;Mikey Dickerson&lt;/a&gt;'s on &lt;a href="http://en.oreilly.com/mysql2011/public/schedule/detail/17138"&gt;detecting data drift&lt;/a&gt;.&lt;/p&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-9215033455622445914?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/dfSev2-ZGWaoA5HsD9MkWDcHYm8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dfSev2-ZGWaoA5HsD9MkWDcHYm8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/dfSev2-ZGWaoA5HsD9MkWDcHYm8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/dfSev2-ZGWaoA5HsD9MkWDcHYm8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/9mTev0_vK6I" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/9215033455622445914/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=9215033455622445914" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/9215033455622445914?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/9215033455622445914?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/9mTev0_vK6I/new-generation-of-google-mysql-tools.html" title="A new generation of Google MySQL tools" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><georss:featurename>Google Mountain View, 1600 Amphitheatre Parkway, Mountain View, CA, United States</georss:featurename><georss:point>37.4228 -122.085</georss:point><feedburner:origLink>http://flamingcow.dilian.org/2011/04/new-generation-of-google-mysql-tools.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUEFQnw8fSp7ImA9Wx5QEEw.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-6908422114514192044</id><published>2010-08-22T22:27:00.000-07:00</published><updated>2010-08-28T10:46:53.275-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-08-28T10:46:53.275-07:00</app:edited><title>Net Neutrality?</title><content type="html">&lt;div&gt;A few weeks ago, Google announced a &lt;a href="http://googlepublicpolicy.blogspot.com/2010/08/joint-policy-proposal-for-open-internet.html"&gt;starting point framework for discussion of net neutrality&lt;/a&gt;.  It's been attacked from all sides for lots of reasons.  I was having trouble forming an opinion in any direction (other than some knee-jerk Google defense), until I read &lt;a href="http://www.reddit.com/r/AskReddit/comments/d2kwy/reddit_what_the_heck_is_net_neutrality/"&gt;this&lt;/a&gt;.  It made me realize that the problem with the Google proposal isn't specific stances, but lack of technical detail; it makes it hard for technical people to have a rational discussion about this.  Even the reddit post doesn't spell this out wonderfully.&lt;/div&gt;&lt;div&gt;Instead, how about some simple (technical) questions?  My personal opinions are in [].  Note "may" instead of "can"; all of these things are technically possible today (which is how we got here), so we're talking about industry self-regulation or government regulation.&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;May ISPs prioritize some protocols over others?&lt;/b&gt; [yes]&lt;br /&gt;e.g. &lt;i&gt;may an ISP give HTTP traffic priority over bittorrent?&lt;/i&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Must users be able to change these settings, including disabling prioritization?&lt;/b&gt; [yes]&lt;br /&gt;This may be a tricky network architecture problem if the ISP has choke points that aren't the DSL or cable line.  If the ISP oversubscribes their own upstream links, they have to propagate the user preference through the whole network.&lt;/li&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Is it opt-in or opt-out?&lt;/b&gt; [opt-out; this is probably useful for most users]&lt;/li&gt;&lt;/ol&gt;&lt;li&gt;&lt;b&gt;May prioritization consider sub-protocols?&lt;/b&gt; [yes]&lt;br /&gt;e.g.&lt;i&gt; may an ISP give text/html HTTP responses priority over video/webm responses?&lt;/i&gt;&lt;br /&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;May ISPs prioritize some destinations over others?&lt;/b&gt; [no]&lt;br /&gt;e.g. &lt;i&gt;may an ISP give google.com traffic priority over bing.com traffic?&lt;span class="Apple-style-span" style="font-style: normal;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;User choice probably doesn't make sense here, as it's hard to argue that this type of prioritization benefits users.&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;May ISPs accept money from destination sites for prioritization?&lt;/b&gt; [no]&lt;br /&gt;e.g. &lt;i&gt;may Verizon take $10 million/year from Google to prioritize traffic to google.com?&lt;/i&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;May ISPs prioritize some users over others?&lt;span class="Apple-style-span" style="font-weight: normal;"&gt; [yes]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;e.g. &lt;i&gt;may an ISP provide more expensive service options that prioritize traffic?&lt;br /&gt;&lt;/i&gt;&lt;/span&gt;&lt;/b&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;May ISPs prioritize users punitively?&lt;/b&gt; [no]&lt;br /&gt;e.g. &lt;i&gt;may an ISP move a high-traffic user to a lower priority?&lt;br /&gt;&lt;br /&gt;&lt;/i&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;May ISPs block some protocols?&lt;span class="Apple-style-span" style="font-weight: normal;"&gt; [no]&lt;/span&gt;&lt;br /&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;e.g. &lt;i&gt;may an ISP block bittorrent entirely?&lt;br /&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;This typically comes up as an anti-piracy solution.  [Protocols themselves are never inherently anti-copyright (even if 95% of their use is for software/media piracy); the courts get this one wrong frighteningly often.]&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/span&gt;&lt;/b&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;May ISPs block some destinations? &lt;/b&gt;[no]&lt;br /&gt;e.g. &lt;i&gt;may an ISP block porn sites?&lt;br /&gt;&lt;span class="Apple-style-span" style="font-style: normal;"&gt;This typically comes up as a protect-the-children solution.  [Filtering technology has far too many false positives, and the same technology available to ISPs is available to end users.  Parents concerned about what their children are exposed to can install home solutions, which children will bypass just as easily as they bypass ISP solutions.]&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/i&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;May ISPs charge per-byte?&lt;/b&gt; [yes]&lt;br /&gt;e.g. &lt;i&gt;may ISPs offer cheaper plans that charge per-megabyte, possibly after the user passes a threshold?&lt;/i&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Must ISPs provide per-byte users tools to see their usage?&lt;/b&gt; [yes]&lt;/li&gt;&lt;li&gt;&lt;b&gt;Must ISPs only use the word "unlimited" for plans which are truly unlimited?&lt;/b&gt; [yes]&lt;br /&gt;e.g. &lt;i&gt;are ISPs prohibited from calling a plan with a 250GB cap "unlimited" in advertising?&lt;/i&gt;&lt;/li&gt;&lt;/ol&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;b&gt;Must ISPs disclose their answers to all of these questions?&lt;/b&gt; [yes]&lt;br /&gt;e.g. &lt;i&gt;"We prioritize some destinations over others."&lt;/i&gt;&lt;br /&gt;&lt;ol&gt;&lt;li&gt;&lt;b&gt;Must ISPs disclose details?&lt;/b&gt; [yes]&lt;br /&gt;e.g. &lt;i&gt;"We prioritize google.com over bing.com."&lt;/i&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-6908422114514192044?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/DJ-ZbPwmhxFEFUkms3uE1AYMIS4/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/DJ-ZbPwmhxFEFUkms3uE1AYMIS4/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/DJ-ZbPwmhxFEFUkms3uE1AYMIS4/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/DJ-ZbPwmhxFEFUkms3uE1AYMIS4/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/EWuboWDeYZI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/6908422114514192044/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=6908422114514192044" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6908422114514192044?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6908422114514192044?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/EWuboWDeYZI/net-neutrality.html" title="Net Neutrality?" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2010/08/net-neutrality.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMCQX07fip7ImA9WxFVGE8.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-8771512362033360935</id><published>2010-06-17T16:55:00.001-07:00</published><updated>2010-06-17T17:54:20.306-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-06-17T17:54:20.306-07:00</app:edited><title>Playing with filters</title><content type="html">I was up in Russian River a few weekends ago on a lazy afternoon, boyfriend snoozing on the couch.  I had just bought a bunch of filters for the camera; they're cheap relative to other camera accessories, and I thought they might be fun to play with.  Here's a shot of the view from the deck with no filter:&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/Xc8NHORzCXiFnpGvRnu3dQ?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_EOWtL8YFPmo/TBq0z2z9-AI/AAAAAAAAMK0/OXCJag86sFo/s400/P1010445.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;First, linear polarizer (the GF1 does contrast auto-focus, so you can use them, and this was focused to infinity anyway):&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/UcAfF1F2hJiY2kfssXwqxw?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_EOWtL8YFPmo/TBq02xm917I/AAAAAAAAMLA/x9FPjfMWLI8/s400/P1010446.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Rotating the linear polarizer seemed to have no effect, which isn't what should happen, AFAIK.  Switch to the circular polarizer (which is really a linear polarizer with a scatter filter behind it).  Rotating this does something; here are the two extremes:&lt;/div&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/awHGMShWCeq0D0zp4VwxQQ?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_EOWtL8YFPmo/TBq04bllxEI/AAAAAAAAMLM/VyTePhUaxCI/s288/P1010447.jpg" style="float: left; clear: none;" /&gt;&lt;/a&gt;&lt;a href="http://picasaweb.google.com/lh/photo/X03baJf8LBA4I9-gpUGTfg?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_EOWtL8YFPmo/TBq07fJ9qCI/AAAAAAAAMLc/lVkc2vYAgpk/s288/P1010448.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;Note the emphasis on the sky in the left image and on the trees in the right (light polarized differently from each?).  The left is 1/2500s, right is 1/1600s (less light coming from the trees than the sky).&lt;div&gt;&lt;br /&gt;&lt;div&gt;Next up: stacking a linear polarizer in front of the circular one (light -&gt; linear -&gt; circular -&gt; lens).  In theory, this creates a variable neutral-density filter controllable by the alignment of the two polarizers.  However, the alignment of the front polarizer against the outside light matters too, so it's not perfectly "neutral" (I think that's responsible for the blue tint below).  Extremes:&lt;/div&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/vT7FtNt3qvLWAH0JIxoicw?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_EOWtL8YFPmo/TBq0_r6eQMI/AAAAAAAAML8/iAwtTnUGP6Q/s288/P1010450.jpg" style="float: left; clear: none;" /&gt;&lt;/a&gt;&lt;a href="http://picasaweb.google.com/lh/photo/kXIvrPCtP9Dsb9q-I6hcbA?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_EOWtL8YFPmo/TBq09vW2XVI/AAAAAAAAMLo/7ZTj5gobUcY/s288/P1010449.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;These are auto-shutter-speed, so the significance of the difference isn't apparent: left is 1/1600s, right is 1/500s (and still much darker).&lt;/div&gt;&lt;div&gt;Next up: colors.  As you would imagine, these make the image...colored.  If you then desaturate, though, you can focus on different things.  mikeyd points out that you can get almost the same effect digitally, except I might be able to pick up a bit more detail by chopping out the light I don't want before it gets to the sensor.&lt;/div&gt;&lt;div&gt;Yellow (nice glow along the horizon):&lt;/div&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/f3o60DsMF5Ks4aXmXtXBMw?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_EOWtL8YFPmo/TBq1GNAT0LI/AAAAAAAAMMs/iHjG-tNq5v8/s400/P1010453.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Red (very flat; not much anywhere near red in this image):&lt;/div&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/znr8UuCJ_fpSW52gf0DnkA?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_EOWtL8YFPmo/TBq1HSDqz-I/AAAAAAAAMM4/TFw21ZRP0ME/s400/P1010454.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Blue (totally blown out from the sky, but you can see shadow detail that you can't see in other images here):&lt;/div&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/0wwxDUij5yElIToTpEoQ-g?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_EOWtL8YFPmo/TBq1IsekRkI/AAAAAAAAMNE/gQs5rugaKkA/s400/P1010455.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Green (similar to yellow, with a bit more sky):&lt;/div&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/zrCl-1WD4H9KESk7FzgVng?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_EOWtL8YFPmo/TBq1LvqptBI/AAAAAAAAMNQ/IU-0TNrmJkI/s400/P1010456.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;And then we fall off the visual spectrum and into IR, relying on the sensor to pick up non-visual light, even past its built-in hot mirror.&lt;/div&gt;&lt;div&gt;Near IR (starting to lose the sky):&lt;/div&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/OQ92XYSL3KkZgt8UIfhvdA?feat=embedwebsite"&gt;&lt;img src="http://lh6.ggpht.com/_EOWtL8YFPmo/TBq1N6mYN3I/AAAAAAAAMNo/av0bb6nVC_w/s400/P1010457.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Deep IR (sky gone, significant shadow highlights):&lt;/div&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/yu1Y9rPxS8JcByWGWR6VxQ?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_EOWtL8YFPmo/TBq1UK60KnI/AAAAAAAAMOQ/soLIXtIfCCU/s400/P1010460.jpg" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;These take patience and a tripod, and you can't shoot action; the first is 1/6s and the second is 8s (yes, 8 seconds).&lt;/div&gt;&lt;/div&gt;&lt;div&gt;List of filters used here:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/B00004ZCB8"&gt;Tiffen Linear Polarizer&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/B00004ZCAU"&gt;Tiffen Circular Polarizer&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/B00004ZCAQ"&gt;Tiffen 8 Yellow&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/B00004ZCA0"&gt;Tiffen 25 Red&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/B00004ZCAD"&gt;Tiffen 47 Blue&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/B00004ZCAC"&gt;Tiffen 11 Green&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/B0000AI1FZ"&gt;Hoya RM-72 IR&lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.amazon.com/gp/product/B00004ZCAP"&gt;Tiffen 87 IR&lt;/a&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-8771512362033360935?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/fL5GYnGYgtrvsVlFyNCerYQT1Gw/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fL5GYnGYgtrvsVlFyNCerYQT1Gw/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/fL5GYnGYgtrvsVlFyNCerYQT1Gw/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/fL5GYnGYgtrvsVlFyNCerYQT1Gw/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/fnFATECAwmE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/8771512362033360935/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=8771512362033360935" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/8771512362033360935?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/8771512362033360935?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/fnFATECAwmE/playing-with-filters.html" title="Playing with filters" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh3.ggpht.com/_EOWtL8YFPmo/TBq0z2z9-AI/AAAAAAAAMK0/OXCJag86sFo/s72-c/P1010445.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2010/06/playing-with-filters.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CEMFSHgzeyp7ImA9WxFSEEw.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-3402698561760885530</id><published>2010-04-10T14:10:00.000-07:00</published><updated>2010-04-11T12:00:19.683-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-11T12:00:19.683-07:00</app:edited><title>Home video re-think</title><content type="html">&lt;h3&gt;Choosing a platform&lt;/h3&gt;&lt;br /&gt;There's no shortage of alternatives to the traditional cable box + TV model, from cable provider DVRs to &lt;a href="http://www.tivo.com/"&gt;TiVo&lt;/a&gt; (yes, people actually still own those) to more obscure offerings like &lt;a href="http://www.myka.tv/"&gt;Myka&lt;/a&gt;, or &lt;a href="http://www.mythtv.org/"&gt;MythTV&lt;/a&gt; running on your closest whitebox.  However, if you want to combine easy content sourcing, central storage/management with streaming, a nice remote control interface and solid, attractive hardware, there's really only one option: for better or worse, Apple's &lt;a href="http://www.apple.com/itunes/"&gt;iTunes&lt;/a&gt;/&lt;a href="http://en.wikipedia.org/wiki/Front_Row_(software)"&gt;Front Row&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Electronics&lt;/h3&gt;&lt;br /&gt;I already had an iMac that had ended up at a common-area computer desk in my apartment.  This seemed a reasonable choice for a media server, though I suppose I could've shot for something that had a concept of running headless (another &lt;a href="http://www.apple.com/macmini/"&gt;Mac Mini&lt;/a&gt;).&lt;div&gt;&lt;br /&gt;&lt;div&gt;Output streams to the TVs had two options: the Mac Mini, or an &lt;a href="http://www.apple.com/appletv/"&gt;Apple TV&lt;/a&gt;.  The Apple TV is smaller and cheaper, but you're locked out of all the real computing functionality (the LAN-party-on-TVs option disappears). It would be nice to be able to control these with just Apple's &lt;a href="http://store.apple.com/us_smb_78313/product/MC377LL/A"&gt;media remote&lt;/a&gt;, but it's just not practical; OS X is interrupty as hell, with updates and license agreements splattered all over.  The &lt;a href="http://www.amazon.com/gp/product/B0011FOOI2/ref=oss_product"&gt;diNovo Mini&lt;/a&gt; makes a decent keyboard/mouse combo that you can stuff in a drawer, but don't expect to game on it.&lt;/div&gt;&lt;div&gt;As actual displays, I went with &lt;a href="http://www.samsung.com/us/consumer/tv-video/televisions/led-tv/UN40B7000WFUZA/index.idx?pagetype=prd_detail&amp;amp;returnurl="&gt;LED-backlit Samsung LCDs&lt;/a&gt;, for the lower power usage and the light weight for wall hanging.  Add in &lt;a href="http://www.monoprice.com/products/product.asp?c_id=102&amp;amp;cp_id=10246&amp;amp;cs_id=1024603&amp;amp;p_id=5994&amp;amp;seq=1&amp;amp;format=2"&gt;some&lt;/a&gt; &lt;a href="http://www.monoprice.com/products/product.asp?c_id=102&amp;amp;cp_id=10218&amp;amp;cs_id=1021802&amp;amp;p_id=5576&amp;amp;seq=1&amp;amp;format=2"&gt;cables&lt;/a&gt; and we're good to go...except that it's all sitting on the floor.&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Wall mounting&lt;/h3&gt;&lt;br /&gt;Fortunately, my two TVs were wall mount efforts #6 and 7 for Kacirek, so this went really smoothly.  I picked up &lt;a href="http://www.monoprice.com/products/product.asp?c_id=108&amp;amp;cp_id=10828&amp;amp;cs_id=1082812&amp;amp;p_id=5918&amp;amp;seq=1&amp;amp;format=2"&gt;wall mount kits&lt;/a&gt; from Monoprice.  In short: stud finder, level, pilot holes, lag bolts, bolts to the TV, hang, done.  There are even nice &lt;a href="http://www.amazon.com/gp/product/B000UWI2LC/ref=oss_product"&gt;wall mount kits for Mac Minis&lt;/a&gt;, naturally at more than twice the price of the LCD mounts, since they count as "designer".  The Mac Mini power adapter fits really nicely in a cable-management cutout at the back of the TV.  Add in an extension cord and some cable management from Fry's, and voila:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a href="http://picasaweb.google.com/lh/photo/FY9Bo4yPjIWO16UqReWGrQ?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_EOWtL8YFPmo/S8ITp8wqASI/AAAAAAAAJtI/Xd_alVApBEM/s288/P1000508.JPG" style="float: left;" /&gt;&lt;/a&gt;&lt;a href="http://picasaweb.google.com/lh/photo/3kIAN5d61p0IWjHuR6y0JA?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_EOWtL8YFPmo/S8ITr5B6G0I/AAAAAAAAJtM/mS8AOgOD-zw/s288/P1000509.JPG" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;h3&gt;Front Row love and hate&lt;/h3&gt;&lt;br /&gt;Front Row is, at times, awesome.  It remembers pause position across different streaming clients.  The interface is simple and useful.  Over a fast network, seeking and fast-forward are lightning-quick.  It doesn't let you set a default streaming source, but that only adds a couple of clicks.&lt;/div&gt;&lt;div&gt;Sometimes, it's horribly frustrating.  It hangs indefinitely and uninterruptably trying to load remote library contents.  It forgets pause position, even on the same machine.  None of these are repeatable, so trying to solve them seems nigh-impossible.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;h3&gt;Unofficial content&lt;/h3&gt;&lt;br /&gt;iTunes also doesn't want you using their fancy toys with torrented files; it won't let you add them to your library, and if you change the file type to work around that, it still won't stream them to remote clients.  Fortunately, this is pretty simple to work around.  You need &lt;a href="http://www.apple.com/quicktime/pro/"&gt;Quicktime Pro&lt;/a&gt;, which comes with Final Cut Studio, is cheap to buy separately, or can be obtained by whatever means you like.  It hides in Utilities once installed, and is easy to confuse with Apple's stripped-down but base-install Quicktime Player.  Follow steps 1-4 &lt;a href="http://www.apple.com/quicktime/tutorials/hinttracks.html"&gt;here&lt;/a&gt;, and your torrented content is now draggable into iTunes and streamable to Front Row clients.  It doesn't re-encode unless you do steps 5-8, so it's fast and you don't lose quality.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;h3&gt;Automatic wake-up&lt;/h3&gt;&lt;br /&gt;I also wanted waking up the Mini clients to automatically wake up the iMac file server, so I didn't have to leave it running all the time.  Again, this isn't too hard.  First, pick up &lt;a href="http://www.bernhard-baehr.de/"&gt;SleepWatcher&lt;/a&gt;, clearly written and packaged by someone who's never heard of dmg or a Makefile (but it works).  Install &lt;a href="http://gsd.di.uminho.pt/jpo/software/wakeonlan/"&gt;wakeonlan&lt;/a&gt;, a tiny little PERL script that sends &lt;a href="http://en.wikipedia.org/wiki/Wake-on-LAN"&gt;Wake-on-LAN&lt;/a&gt; magic packets.  Then, add something to /etc/rc.wakeup like:&lt;/div&gt;&lt;pre&gt;COUNT=0&lt;br /&gt;while [ ${COUNT} -lt 10 ]; do&lt;br /&gt;  /usr/local/sbin/wakeonlan 00:23:df:fe:c6:6d&lt;br /&gt;  COUNT=$((COUNT + 1))&lt;br /&gt;  sleep 1&lt;br /&gt;done&lt;/pre&gt;&lt;div&gt;Your path to wakeonlan, MAC address (of your fileserver) and packet count (and time) required for your network interface to come online may vary.&lt;/div&gt;&lt;br /&gt;&lt;h3&gt;Hello, iPad?&lt;/h3&gt;&lt;br /&gt;&lt;div&gt;It would be really great to be able to pull a Minority Report-style video transfer, moving streaming video seamlessly from a TV to the iPad and walking away with it.  This is a pipe dream, however, until Apple decides to actually support streaming on the iPad.  Seriously, Apple, I have to plug this thing in and copy the whole video to it to watch it?&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-3402698561760885530?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/K9A3eSKKZLbaMSq6ZwBXrx1_FZA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/K9A3eSKKZLbaMSq6ZwBXrx1_FZA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/K9A3eSKKZLbaMSq6ZwBXrx1_FZA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/K9A3eSKKZLbaMSq6ZwBXrx1_FZA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/ZWYou6ArJKc" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/3402698561760885530/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=3402698561760885530" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/3402698561760885530?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/3402698561760885530?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/ZWYou6ArJKc/home-video-re-think.html" title="Home video re-think" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh4.ggpht.com/_EOWtL8YFPmo/S8ITp8wqASI/AAAAAAAAJtI/Xd_alVApBEM/s72-c/P1000508.JPG" height="72" width="72" /><thr:total>3</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2010/04/home-video-re-think.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUMEQH84eCp7ImA9WxFSEE0.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-7103587327084625087</id><published>2010-04-07T14:11:00.001-07:00</published><updated>2010-04-11T10:36:41.130-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-11T10:36:41.130-07:00</app:edited><title>(Wireless) network optimization, 2010 edition</title><content type="html">After getting the Internet connection all tuned up, it's time to talk network speed.&lt;div&gt;&lt;br /&gt;&lt;h3&gt;How fast do you need to go?&lt;/h3&gt;&lt;div&gt;Talking about gigabit speeds around the office drew some incredulity.  Most users seem to be used to talking about Internet connection speeds in the sub-10mbit range, so a 10mbit hub (which my new apartment came prewired with) and &lt;a href="http://en.wikipedia.org/wiki/802.11b"&gt;802.11b&lt;/a&gt; (6mbit/s TCP) or at least &lt;a href="http://en.wikipedia.org/wiki/802.11g"&gt;802.11g&lt;/a&gt; (~30mbit/s TCP) will pretty much suffice.  Political arguments about the mess that is US last-mile Internet connections aside, however, there are expensive options at higher speeds.  Some areas have FiOS (though Verizon has apparently &lt;a href="http://www.engadget.com/2010/03/27/verizon-shelves-plans-for-future-fios-rollouts-relocations-to-m/"&gt;stopped rolling it out&lt;/a&gt;), and Comcast has a 50mbit/s "Extreme" plan in my area for $115/month.  &lt;a href="http://en.wikipedia.org/wiki/DOCSIS#Speed_tables"&gt;DOCSIS 3&lt;/a&gt; supports up to ~160mbit/s link speed.  Broadband speeds don't obey Moore's law (mostly due to the enormous infrastructure investment required to deploy new tech), but we'll still probably see cable plans breaking the 100mbit/s barrier in 3 or 4 years max.  In short, it's a &lt;a href="http://en.wikipedia.org/wiki/Gigabit_Ethernet"&gt;gigabit ethernet&lt;/a&gt; (~700mbit/s in real life) and &lt;a href="http://en.wikipedia.org/wiki/802.11n"&gt;802.11n&lt;/a&gt; (~150mbit/s with today's gear) world for the short- to medium-term.&lt;/div&gt;&lt;div&gt;&lt;h3&gt;Defining your users&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;My use cases for wireless at home divide pretty neatly into two categories: high-bandwidth, low-latency streaming to fixed points (Mac Minis hooked up to my TVs), and bursty-bandwidth, can-survive-momentary-latency clients that move around a lot (laptop, cellphone, iPad).  I'd like both to be able to max out my Internet connection, but the video streaming needs to be able to do better inside my network (streaming from my iMac).  This may get murkier once Apple get iTunes streaming to the iPad working.&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;h3&gt;The first hop&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;No amount of optimization on the wireless side is going to help if the cable modem to router hop can't push the full speed of the 'net connection (this presumes that they're two different devices for you).  First, both should support GigE (I have a &lt;a href="http://www.amazon.com/Motorola-SB6120-SURFboard-eXtreme-Broadband/dp/B001UI2FPE"&gt;Motorola SB6120&lt;/a&gt; and a &lt;a href="http://www.amazon.com/D-Link-DIR-855-Xtreme-802-11n-Router/dp/B00127UWV2"&gt;D-Link DIR-855&lt;/a&gt;).  It's harder than it should be to verify the connection speed between these two; in the end, I had to force the link on the router end to 1000mbit/s-only, then make sure it still connected.&lt;/div&gt;&lt;div&gt;My apartment isn't wired ideally, so the cable modem and router are in different places.  The apartment has ethernet throughout, but it's only wired with 2 pairs (out of the 4 pairs in an RJ45 connector); that's only sufficient for 100mbit/s links.  Kacirek brought over the toolkit and we appropriated some telephone wiring to serve as the extra two pairs, replacing the 10mbit hub with an &lt;a href="http://www.monoprice.com/products/product.asp?c_id=105&amp;amp;cp_id=10519&amp;amp;cs_id=1051902&amp;amp;p_id=1068&amp;amp;seq=1&amp;amp;format=2"&gt;ethernet coupler&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;div&gt;&lt;h3&gt;Going N-only&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;The 802.11b to 802.11g migration was a mess; networks effectively dropped back to all-B in the presence of even a single B device.  G to N isn't as bad, but it's not great; 802.11 continues to accumulate &lt;a href="http://en.wikipedia.org/wiki/802.11n#Backward_compatibility"&gt;backwards-compatibility hacks&lt;/a&gt; all over the place.  However, I was surprised to find that every device except my old T60 supports N, &lt;i&gt;including&lt;/i&gt; my Nexus One.  It didn't ship with the support, and Google never indicated that an upgrade to it was forthcoming, but it must have snuck out with a firmware upgrade somewhere.  After digging out an old 802.11n mini-PCI card that I bought years ago and upgrading the T60, I was able to switch from G/N to just N.  This is probably a significant win, if you can manage to upgrade all your devices.  If not, confining the older ones to 2.4GHz (leaving 5GHz to pure-N, rather than A/N) is probably your best bet.&lt;/div&gt;&lt;div&gt;&lt;h3&gt;There's N, then there's N&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;802.11n has to be one of the most consumer-confusing specs ever.  N works by using multiple antennas to build virtual "spatial streams".  For example, radio one has antennas 1A and 1B; radio two has 2A, 2B and 2C.  The silicon supports 2 spatial channels, which get built between, e.g. 1A and 2B, 1B and 2C.  These spatial channels are treated as separate links, even though they're on the same frequency.  There are 16 possible antenna/radio configurations and 30 antenna/radio/spatial channel configurations.  The configurations are abbreviated AxB:C (A: transmit radios/antennas, B: receive radios/antennas, C: processor-supported spatial channels).  The spec goes up to 4x4:4.  Unfortunately, this means that 3-antenna systems aren't necessarily 3-stream (and most sold today aren't).  You can't have more streams than your lowest radio/antenna count, and your maximum speed is determined by your &lt;a href="http://en.wikipedia.org/wiki/802.11n#Data_rates"&gt;number of streams&lt;/a&gt; and frequency width.  N can use 20MHz or 40MHz of radio spectrum.  The DIR-855 I bought seems to be either 2x3:2 or 3x3:2; 300mbit/s max at 40MHz.  It seems to be impossible to buy 3- or 4-stream consumer gear at the moment (and you need client gear to support it, so it wouldn't be too useful).&lt;/div&gt;&lt;div&gt;&lt;h3&gt;2.4GHz vs. 5GHz&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;802.11n makes the frequency choice even harder than it used to be.  2.4GHz is an overpopulated ghetto unless you live on double-digit acreage.  It penetrates walls significantly better than 5GHz, but that's a blessing and a curse: you can use it from further away, but your neighbors interfere from further away.  Even worse, at 40MHz, 802.11n takes 2 of the 3 non-overlapping 2.4GHz channels.  That means that if you can see two or more neighboring access points, you're not getting full speed.  The penetration advantages are significant, though: my iPad gets 6mbit/s link speed on 5GHz at the furthest point in my apartment from my access point.   At 2.4GHz, it gets 26mbit/s.&lt;/div&gt;&lt;div&gt;Dual-band solutions help, but you have to be careful.  Assign different SSIDs to your 2.4GHz and 5GHz networks, so you can force clients to one or the other.  Put things like video streaming in 5GHz, where a neighbor download isn't likely to cause hiccups.  Test your other devices at maximum range, and see whether you can live with the 5GHz signal level.&lt;/div&gt;&lt;div&gt;&lt;h3&gt;A little more range&lt;/h3&gt;&lt;/div&gt;&lt;div&gt;If you'd like to squeak just a little more range out of your access point, either to be able to use 5GHz where you would've used 2.4GHz, or to be able to reach far-away spots with anything at all, consider replacement antennas.  Higher-grade access points support them, and they'll buy you a little bit, though don't expect miracles.  I picked up 3 of &lt;a href="http://www.amazon.com/gp/product/B000ERCNZY/ref=oss_product"&gt;these&lt;/a&gt;, which help a bit without taking it to ridiculous extremes.&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;h3&gt;Other optimizations&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Location, location, location: put your access point in the middle of your coverage area.  It's the simplest thing you can do to get massive speed gains.&lt;/div&gt;&lt;div&gt;Make sure 802.11n short guard interval is enabled: without it, you lose about 10% of speed.&lt;/div&gt;&lt;div&gt;Plug it in: if you can wire it, do.  This is especially true for things like home fileservers, as wiring things that you copy from &lt;b&gt;to &lt;/b&gt;wireless effectively doubles your transfer speed and halves your latency.&lt;/div&gt;&lt;div&gt;Screw the neighbors: some access points have options to disable being friendly to other 802.11a/b/g devices.&lt;/div&gt;&lt;div&gt;Disable all the complex router filtering: turn off web filtering, try things without QoS, disable the "firewall" and "security" features.  Usually processors in routers are pretty light-weight, and you can be wasting CPU time on faux-security that could be spent moving more packets faster.&lt;/div&gt;&lt;div&gt;Fix DNS: good chunks of interactive browsing time is spent waiting for DNS servers.  Your router may be doing DNS relaying (running a local DNS server); try with and without it, to see if it sucks.  If your ISP's DNS servers suck, try &lt;a href="http://code.google.com/speed/public-dns/"&gt;Google Public DNS&lt;/a&gt;; it's further from you network-wise, so it can't possibly be as fast as your ISP's DNS servers could be, but it's quite likely faster than they actually are.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-7103587327084625087?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/n6PsMMt4UMr3b0y7NYcd9eJ-I4U/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/n6PsMMt4UMr3b0y7NYcd9eJ-I4U/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/n6PsMMt4UMr3b0y7NYcd9eJ-I4U/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/n6PsMMt4UMr3b0y7NYcd9eJ-I4U/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/aoZNdP30k-4" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/7103587327084625087/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=7103587327084625087" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/7103587327084625087?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/7103587327084625087?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/aoZNdP30k-4/wireless-network-optimization-2010.html" title="(Wireless) network optimization, 2010 edition" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2010/04/wireless-network-optimization-2010.html</feedburner:origLink></entry><entry gd:etag="W/&quot;Ck4MRHw-eCp7ImA9WxFTFU8.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-576605899695737859</id><published>2010-04-05T19:18:00.001-07:00</published><updated>2010-04-05T19:29:45.250-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-04-05T19:29:45.250-07:00</app:edited><title>Comcast hacking</title><content type="html">I finally gave up on my principled stand against traffic shaping and switched to Comcast when I moved.  The 10x speed for the same price over Speakeasy might have had something to do with it.  It's been an interesting road getting it working as I wanted, and here's the notes list:&lt;div&gt;&lt;ul&gt;&lt;li&gt;D-Link modems don't work (well, at least).  The one I got needed a custom firmware to work with Comcast according to D-Link's website, and the instructions for flashing the firmware included running a local TFTP server, then telnetting to the modem.  Connection refused.  Classy, guys.  Took it back to Fry's, noticed that every single D-Link and Linksys cable modem box had a returned sticker on it.  Bought a &lt;a href="http://www.amazon.com/Motorola-SB6120-SURFboard-eXtreme-Broadband/dp/B001UI2FPE"&gt;Motorola SB6120&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/DOCSIS"&gt;DOCSIS&lt;/a&gt; seems to support remote firmware flashing.  The modem comes up with a firmware with the string "walledgarden" in the name, and all your connections get redirected to Comcast's activation page.  The redirection is only DNS-level, though; switch to &lt;a href="http://code.google.com/speed/public-dns/"&gt;Google Public DNS&lt;/a&gt; servers on your router/DHCP server/computer and you can surf just fine.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.comcast.com/Corporate/Learn/HighSpeedInternet/speedcomparison.html"&gt;Speed&lt;/a&gt; seems to be enforced per-account, not per-link.  That means that they can't apply any speed package to you until you go through the activation wizard, which registers your modem's HFC-side MAC address with Comcast.  The "walledgarden" speed actually appears to be Comcast's Ultra package (22/5mbps).  That means that if you're not signed up for Ultra or Extreme (50/10), but chose Performance (12/2) or Blast! (16/2) instead, it's actually in your best interest to not activate.&lt;/li&gt;&lt;li&gt;If you have to activate, the technician workflow is way easier: no installing software that messes with your network settings, and it works in Linux.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;More on the great wireless network project coming soon.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-576605899695737859?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/xfqhPJ2yfUWOWdLPD9LRWjPH5qA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xfqhPJ2yfUWOWdLPD9LRWjPH5qA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/xfqhPJ2yfUWOWdLPD9LRWjPH5qA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/xfqhPJ2yfUWOWdLPD9LRWjPH5qA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/cJmofxIlPec" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/576605899695737859/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=576605899695737859" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/576605899695737859?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/576605899695737859?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/cJmofxIlPec/comcast-hacking.html" title="Comcast hacking" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2010/04/comcast-hacking.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkEFQno5eyp7ImA9WxBaFko.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-1811865821736004011</id><published>2010-03-26T23:00:00.000-07:00</published><updated>2010-03-26T23:16:53.423-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-26T23:16:53.423-07:00</app:edited><title>Fun with map visualizations</title><content type="html">I've been playing with Google's &lt;a href="http://code.google.com/apis/charttools/"&gt;Chart Tools&lt;/a&gt; quite a bit lately.&lt;div&gt;&lt;br /&gt;&lt;div&gt;I did some internal stuff at work (that unfortunately I can't show here) to visualize problems where you have lots of points, all connected by lines that you know the ideal length of, but where those lengths don't lay out properly in 2 dimensions, and figuring out where to put the points is hard anyway.&lt;/div&gt;&lt;div&gt;The most elegant solution seems to be a &lt;a href="http://en.wikipedia.org/wiki/Force-based_algorithms"&gt;force-directed graph&lt;/a&gt;: pretend the lines are springs, randomize the initial point positions, and simulate physics iteratively.  It's slow, and the algorithm is easy to screw up (don't forget friction, or they just orbit each other), but the results are impressive: consistent layouts that are rotation-agnostic each time you run the algorithm.  I ended up rendering the results using the static &lt;a href="http://code.google.com/apis/chart/docs/gallery/scatter_charts.html"&gt;scatter chart&lt;/a&gt;.  Sadly, the URL syntax is arcane, and the error feedback is nonexistent.&lt;/div&gt;&lt;div&gt;Today, I got to build a visualization that &lt;a href="http://www.google.com/appserve/fiberrfi"&gt;went public&lt;/a&gt;:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/_EOWtL8YFPmo/S62gp9ZpEYI/AAAAAAAAIsY/5yMtHV_wy0c/s1600/map.png"&gt;&lt;img style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 221px;" src="http://4.bp.blogspot.com/_EOWtL8YFPmo/S62gp9ZpEYI/AAAAAAAAIsY/5yMtHV_wy0c/s400/map.png" border="0" alt="" id="BLOGGER_PHOTO_ID_5453191366532731266" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;We had lots of data from the fiber-to-the-home request-for-information site, and needed a way to visualize it.  This is a &lt;a href="http://code.google.com/apis/visualization/documentation/gallery/geomap.html"&gt;geo map&lt;/a&gt; that uses markers.  Unfortunately, the API limits you to 400 points, which wasn't enough, so I (at nmlorg's suggestion) screenshotted the map with 400 points at a time and stitched the results; hacky, but functional.  We couldn't have used the direct rendering anyway, as it does one AJAX call to Google Maps to look up &lt;i&gt;each point&lt;/i&gt; (we were passing in ZIP codes), so it takes ~10 minutes to render.&lt;/div&gt;&lt;div&gt;We considered &lt;a href="http://code.google.com/apis/maps/documentation/staticmaps/"&gt;static maps&lt;/a&gt; (custom icons would've been cool), but the URL length limit makes the effective point limit less than 400, and there's only so much stitching I'll put up with.&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-1811865821736004011?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/SEfUxd7KNhgLWZ9uKpAnD4iqhwE/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SEfUxd7KNhgLWZ9uKpAnD4iqhwE/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/SEfUxd7KNhgLWZ9uKpAnD4iqhwE/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/SEfUxd7KNhgLWZ9uKpAnD4iqhwE/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/fj_6eFrOJlE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/1811865821736004011/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=1811865821736004011" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/1811865821736004011?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/1811865821736004011?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/fj_6eFrOJlE/fun-with-map-visualizations.html" title="Fun with map visualizations" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/_EOWtL8YFPmo/S62gp9ZpEYI/AAAAAAAAIsY/5yMtHV_wy0c/s72-c/map.png" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2010/03/fun-with-map-visualizations.html</feedburner:origLink></entry><entry gd:etag="W/&quot;AkAEQH0-fCp7ImA9WxBbEk8.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-119643970763164976</id><published>2010-03-09T22:18:00.000-08:00</published><updated>2010-03-10T05:45:01.354-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-03-10T05:45:01.354-08:00</app:edited><title>Karaoke project</title><content type="html">Friend and sometimes boss mikeyd had a friend ask him to help her with her entry into a &lt;a href="http://radioalice.radio.com/2010/02/22/alice%E2%80%99s-first-annual-saraoke-party-2/"&gt;karaoke contest&lt;/a&gt;.  Mikey suggested that I could try out the video recording on the &lt;a href="http://www.dpreview.com/reviews/PanasonicGF1/"&gt;new camera&lt;/a&gt;, so I hauled out some of the old sound recording gear, bought some new mics, grabbed the camera and the tripod and headed to Avalon at Mission Bay's penthouse to film.&lt;div&gt;&lt;br /&gt;&lt;div&gt;We shot 14 takes, of which 3 were usable.  Top discard reasons:&lt;div&gt;&lt;ul&gt;&lt;li&gt;Video exposure problems&lt;/li&gt;&lt;li&gt;Artist goofs&lt;/li&gt;&lt;li&gt;Background sound (other people in the room)&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;The internal mic on the camera is pretty much useless for anything but tourist shots, so I recorded audio on &lt;a href="http://www.m-audio.com/products/en_us/MicroTrackII.html"&gt;MicroTrack II&lt;/a&gt;, one mic into each channel.  This gave pretty good (though not perfect) separation of the guitar and vocal tracks.  When I got home, over several days, I cut the audio into multitrack mode with &lt;a href="http://www.apple.com/finalcutstudio/soundtrackpro/"&gt;Soundtrack Pro&lt;/a&gt;, adding more vocal to the mix, a bit of stereo separation, fade in and fade out, and a bit of reverb to the vocals.  I tried a some light auto-tune, but the guitar strumming picked up on the vocal track sounded really, really odd through the auto-tuner.&lt;/div&gt;&lt;div&gt;I used &lt;a href="http://www.apple.com/ilife/imovie/"&gt;iMovie&lt;/a&gt; (I didn't have time for the &lt;a href="http://www.apple.com/finalcutstudio/finalcutpro/"&gt;Final Cut Pro&lt;/a&gt; learning curve) to cut the original audio off, sync the new audio track, trim the junk out of the video, normalize the audio volume, and export 720p to YouTube.  Here are the 3 results:&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;object width="853" height="505"&gt;&lt;param name="movie" value="http://www.youtube.com/v/igHNPZlBuq0&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;rel=0&amp;amp;hd=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/igHNPZlBuq0&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;rel=0&amp;amp;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="853" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;object width="853" height="505"&gt;&lt;param name="movie" value="http://www.youtube.com/v/S4yxDKYAC9Y&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;rel=0&amp;amp;hd=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/S4yxDKYAC9Y&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;rel=0&amp;amp;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="853" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;object width="853" height="505"&gt;&lt;param name="movie" value="http://www.youtube.com/v/EymKYia5x9M&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;rel=0&amp;amp;hd=1"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;embed src="http://www.youtube.com/v/EymKYia5x9M&amp;amp;hl=en_US&amp;amp;fs=1&amp;amp;rel=0&amp;amp;hd=1" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="853" height="505"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Lessons:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Shooting in front of a window? Maybe it would look nicer as a night shot.&lt;/li&gt;&lt;li&gt;Leave plenty of time on either end of both sound and video; trying to sneak the last second out of the clip is lame.&lt;/li&gt;&lt;li&gt;Get a board to show take number to the camera.  Say it clearly on the audio track.  Stop and start between each take, even if they screw up the first note.&lt;/li&gt;&lt;li&gt;Think you've got 2 or 3 good takes out of 14?  You probably need to shoot 30.&lt;/li&gt;&lt;li&gt;Put whoever's providing rhythm on a click track, even if you don't think you'll cut multiple videos together.  Write the BPM on the cue board.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-119643970763164976?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/LkkelBf5ZoZz-1F-vcinOIu3WpA/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LkkelBf5ZoZz-1F-vcinOIu3WpA/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/LkkelBf5ZoZz-1F-vcinOIu3WpA/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/LkkelBf5ZoZz-1F-vcinOIu3WpA/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/BhLZly9oChI" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/119643970763164976/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=119643970763164976" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/119643970763164976?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/119643970763164976?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/BhLZly9oChI/karaoke-project.html" title="Karaoke project" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2010/03/karaoke-project.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUIHQH0_cSp7ImA9WxBUFE8.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-8140855314426365613</id><published>2010-02-28T19:48:00.001-08:00</published><updated>2010-02-28T23:12:11.349-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2010-02-28T23:12:11.349-08:00</app:edited><title>Photo of the day</title><content type="html">Finished jump 16 today.  I'm finally landing the 220 (square foot) parachute without getting dragged along the ground, but I'm still not practicing what I should be in free fall (the last attempts at back flips have ended with me stuck on my back, fighting to get turned over again).  After 3 jumps, I stopped and photographed the next load.  Favorite picture:&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/Q2CONsbgu7xW3X0Hk_Dvmg?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_EOWtL8YFPmo/S4s_QLhZ9lI/AAAAAAAAHmI/ZsjWNh4GS5o/s400/P1000246.jpg" /&gt;&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Second (click and look at it in high res -- I love the grass lighting):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/3hxn0uaU0DAtXF8MftX9Aw?feat=embedwebsite"&gt;&lt;img src="http://lh5.ggpht.com/_EOWtL8YFPmo/S4szmfnM8cI/AAAAAAAAHak/ExYzQlrDJIY/s400/P1000169.JPG" /&gt;&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Pond swooping is supposed to look like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/P-UZVMPvBIMFQicExgV5hA?feat=embedwebsite"&gt;&lt;img src="http://lh3.ggpht.com/_EOWtL8YFPmo/S4s5icr6jlI/AAAAAAAAHgk/y-hs2zq1_kk/s400/P1000189.JPG" /&gt;&lt;/a&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Not like this:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;div&gt;&lt;a href="http://picasaweb.google.com/lh/photo/4ogCIOx_a0xU3eISd3jdYA?feat=embedwebsite"&gt;&lt;img src="http://lh4.ggpht.com/_EOWtL8YFPmo/S4s4nbxnrwI/AAAAAAAAHfc/RqWvGVpf2Zc/s400/P1000185.JPG" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The whole series is &lt;a href="http://picasaweb.google.com/flamingcow/20100228ByEyeFi?feat=directlink"&gt;here&lt;/a&gt;.  Video of plane takeoff &lt;a href="http://www.youtube.com/watch?v=usNUfZT5dmU"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Lessons:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;The EyeFi card is slow (class 4 or less), making burst mode painful once I run out of buffer, especially shooting fast-paced stuff like parachute landings.  Pro X2 may be better (and supports RAW), but not released yet.&lt;/li&gt;&lt;li&gt;No aperture or shutter speed changes in burst mode.  Start shooting near sun, end shooting away, end pictures are really dark.&lt;/li&gt;&lt;li&gt;Auto-focus has trouble with crazy focus changes while shooting video.  Try telling it what object to focus on first?&lt;/li&gt;&lt;li&gt;Pictures are way prettier on the big LED-backlit iMac screen at full size than at 400px on this blog post.&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-8140855314426365613?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/bVR1JhGOlduQ2vTqf3WTxb478ds/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bVR1JhGOlduQ2vTqf3WTxb478ds/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/bVR1JhGOlduQ2vTqf3WTxb478ds/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/bVR1JhGOlduQ2vTqf3WTxb478ds/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/eXOMb3i9yO0" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/8140855314426365613/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=8140855314426365613" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/8140855314426365613?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/8140855314426365613?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/eXOMb3i9yO0/photo-of-day.html" title="Photo of the day" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://lh5.ggpht.com/_EOWtL8YFPmo/S4s_QLhZ9lI/AAAAAAAAHmI/ZsjWNh4GS5o/s72-c/P1000246.jpg" height="72" width="72" /><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2010/02/photo-of-day.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQBSH44fSp7ImA9WxNRF00.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-6036156163917115868</id><published>2009-09-11T15:04:00.000-07:00</published><updated>2009-09-11T15:15:59.035-07:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-09-11T15:15:59.035-07:00</app:edited><title>Confusing BIND with CNAMEs</title><content type="html">&lt;div&gt;Given the zone:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;subdomain IN NS nameserver&lt;/div&gt;&lt;div&gt;nameserver IN CNAME nameserver.otherserver&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;in a BIND server that is both recursive and authoritative, requests without RD (recursion desired) return the NS record, while requests with RD return SERVFAIL.  Changing it to:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;subdomain IN NS nameserver.otherserver&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;fixes the problem, though both resolution trees are perfectly valid.&lt;/div&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-6036156163917115868?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/-lFrlpAUQptfT-o-aoXJZbuBzAo/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-lFrlpAUQptfT-o-aoXJZbuBzAo/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/-lFrlpAUQptfT-o-aoXJZbuBzAo/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/-lFrlpAUQptfT-o-aoXJZbuBzAo/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/_Mkoyi68Wnk" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/6036156163917115868/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=6036156163917115868" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6036156163917115868?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6036156163917115868?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/_Mkoyi68Wnk/confusing-bind-with-cnames.html" title="Confusing BIND with CNAMEs" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>0</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2009/09/confusing-bind-with-cnames.html</feedburner:origLink></entry><entry gd:etag="W/&quot;CkUMRHozeyp7ImA9WxVWEUw.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-6498022543881218932</id><published>2009-02-19T21:55:00.001-08:00</published><updated>2009-02-19T22:11:25.483-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-19T22:11:25.483-08:00</app:edited><title>The odd case of my mugging</title><content type="html">I think I'm writing this down just so I can keep track of it all:&lt;br /&gt;&lt;br /&gt;I was mugged last September on Mountain Shadows Drive in Mountain View, less than a block from my house.  At the time, I was walking home with take-out sushi.  The two black guys who mugged me seemed new to the trade: they were confused when I asked them if I could just give them the cash: first they said yes, then they changed their minds when I only had $14.  They got the cash, my credit cards, and my driver's license (what a pain that is to replace).  They never showed a weapon; apparently, it's a lesser crime if they can manage the robbery without showing one, and I didn't have much incentive to fight.&lt;br /&gt;&lt;br /&gt;The events after that are pieced together from credit card data and a police department that is very efficient and enthusiastic, but doesn't communicate well.  Someone bought a tank of gas at the local shell station with one credit card.  They tried at WalMart, but used the card linked to my ING feeder account at BoA with no money in it, so it was declined.  The muggers apparently gave at least one card to a women named Charlotte Rapuet, who took it to &lt;a href="http://www.bodykneads-dayspa.com/"&gt;Body Kneads&lt;/a&gt; and charged $200 to it.  She got away with this, despite the obvious gender mismatch, because she knew the clerk, a woman named Yadira Hernandez.&lt;br /&gt;&lt;br /&gt;Yadira was caught fairly easily: the credit card company led the police to the spa, where the security camera footage mysteriously didn't match any of the recorded transactions for the evening (she had switched the tape).   She plead no contest, turned in Charlotte, and I watched her sentencing today: 12 days served, probation for 2 years, various fines and fees (court security fee?!?) and restitution to Body Kneads (who got stuck holding the bad credit card charge).  She looks to be in her early twenties and apparently has one child and a very supportive family.  The court waved the public defender fee.&lt;br /&gt;&lt;br /&gt;Charlotte has refused to turn in the person who gave her the card, presumably one of the muggers (she made it to the spa within 2 hours of the mugging).  Her plea hearing is 9am on March 9th.  I intend to attend; this experience has, at the very least, been an interesting lesson in the workings of our justice system.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-6498022543881218932?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/3T6FpWp9FOS-qggrlE9isU8B7K8/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3T6FpWp9FOS-qggrlE9isU8B7K8/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/3T6FpWp9FOS-qggrlE9isU8B7K8/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/3T6FpWp9FOS-qggrlE9isU8B7K8/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/o2tqkh4qLFM" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/6498022543881218932/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=6498022543881218932" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6498022543881218932?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6498022543881218932?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/o2tqkh4qLFM/odd-case-of-my-mugging.html" title="The odd case of my mugging" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>1</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2009/02/odd-case-of-my-mugging.html</feedburner:origLink></entry><entry gd:etag="W/&quot;DUQERno-cCp7ImA9WxVQF00.&quot;"><id>tag:blogger.com,1999:blog-1454940121673019737.post-6121986439588516310</id><published>2009-02-03T16:25:00.000-08:00</published><updated>2009-02-03T16:28:27.458-08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-02-03T16:28:27.458-08:00</app:edited><title>5-packet TCP connection?</title><content type="html">This seems to be valid:&lt;br /&gt;&lt;br /&gt;1) C-&gt;S: SYN&lt;br /&gt;2) S-&gt;C: SYN/ACK&lt;br /&gt;3) C-&gt;S: FIN/ACK&lt;br /&gt;4) S-&gt;C: FIN/ACK&lt;br /&gt;5) C-&gt;S: ACK&lt;br /&gt;&lt;br /&gt;A completely opened and closed TCP connection.  Further, 2 and 3 can both contain data?  Could you get a whole HTTP request/response in this conversation?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/1454940121673019737-6121986439588516310?l=flamingcow.dilian.org' alt='' /&gt;&lt;/div&gt;
&lt;p&gt;&lt;a href="http://feedads.g.doubleclick.net/~a/MoWA7ttRlyXy2BFCMFJVOqHgL1g/0/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MoWA7ttRlyXy2BFCMFJVOqHgL1g/0/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;br/&gt;
&lt;a href="http://feedads.g.doubleclick.net/~a/MoWA7ttRlyXy2BFCMFJVOqHgL1g/1/da"&gt;&lt;img src="http://feedads.g.doubleclick.net/~a/MoWA7ttRlyXy2BFCMFJVOqHgL1g/1/di" border="0" ismap="true"&gt;&lt;/img&gt;&lt;/a&gt;&lt;/p&gt;&lt;img src="http://feeds.feedburner.com/~r/WhereTheFlamingcowRoams/~4/9Ap4UNLzFDE" height="1" width="1"/&gt;</content><link rel="replies" type="application/atom+xml" href="http://flamingcow.dilian.org/feeds/6121986439588516310/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="http://www.blogger.com/comment.g?blogID=1454940121673019737&amp;postID=6121986439588516310" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6121986439588516310?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/1454940121673019737/posts/default/6121986439588516310?v=2" /><link rel="alternate" type="text/html" href="http://feedproxy.google.com/~r/WhereTheFlamingcowRoams/~3/9Ap4UNLzFDE/5-packet-tcp-connection.html" title="5-packet TCP connection?" /><author><name>flamingcow</name><uri>http://www.blogger.com/profile/13461402213917308357</uri><email>noreply@blogger.com</email><gd:image rel="http://schemas.google.com/g/2005#thumbnail" width="16" height="16" src="http://img2.blogblog.com/img/b16-rounded.gif" /></author><thr:total>2</thr:total><feedburner:origLink>http://flamingcow.dilian.org/2009/02/5-packet-tcp-connection.html</feedburner:origLink></entry></feed>

