<?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" gd:etag="W/&quot;A0cERH06eyp7ImA9WxJUFE0.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841</id><updated>2009-07-12T22:30:05.313+08:00</updated><title>Jonathan Levin's Axioms</title><subtitle type="html">Ideas, Rants, Theories vs Getting Things Done</subtitle><link rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/posts/default" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/" /><link rel="next" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default?start-index=26&amp;max-results=25&amp;redirect=false&amp;v=2" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email></author><generator version="7.00" uri="http://www.blogger.com">Blogger</generator><openSearch:totalResults>70</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><link rel="self" href="http://feeds.feedburner.com/WhenPetProjectsBiteBack" type="application/atom+xml" /><feedburner:emailServiceId xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">WhenPetProjectsBiteBack</feedburner:emailServiceId><feedburner:feedburnerHostname xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0">http://feedburner.google.com</feedburner:feedburnerHostname><entry gd:etag="W/&quot;Dk4GR3Y-fip7ImA9WxJVF08.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-7799864616426713200</id><published>2009-06-17T01:33:00.007+08:00</published><updated>2009-07-05T00:28:46.856+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-05T00:28:46.856+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Data mining" /><category scheme="http://www.blogger.com/atom/ns#" term="Marketing" /><category scheme="http://www.blogger.com/atom/ns#" term="Databases" /><category scheme="http://www.blogger.com/atom/ns#" term="Customer satisfaction" /><category scheme="http://www.blogger.com/atom/ns#" term="Conversion rate" /><category scheme="http://www.blogger.com/atom/ns#" term="Business intelligence" /><category scheme="http://www.blogger.com/atom/ns#" term="Decision Support Tools" /><title>Business Intelligence for the People</title><content type="html">&lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Business_intelligence" title="Business intelligence" rel="wikipedia"&gt;Business intelligence&lt;/a&gt; has been talked about for quite a while. Even today, while companies are looking to make budget cuts, some experts are saying that &lt;a href="http://www.silicon.com/research/specialreports/maximising-business-intelligence/beat-the-recession-with-bi-39439890.htm"&gt;BI can be used to beat the recession&lt;/a&gt;.&lt;br /&gt;&lt;br /&gt;When I hear about BI systems, the first thing that comes to my mind is a huge and expensive system that has very powerful servers, that sucks data from many sources and runs some intensive and even more expensive reporting suite. Since I had been involved in projects to set those systems up, I know that it can probably take around a year to complete.&lt;br /&gt;&lt;br /&gt;So everyone is in fact thinking about saving money yet still being competitive and aggressive in the market. On that subject, there are very popular and stable &lt;a href="http://mysqlbarbeque.blogspot.com/2008/03/open-source-etl-tools-vs-commerical-etl.html"&gt;open source BI suites&lt;/a&gt; and similar products (&lt;a href="http://www.kickfire.com/"&gt;kickefire&lt;/a&gt;, &lt;a href="http://www.scaledb.com/"&gt;scaledb&lt;/a&gt;) to achieve both those goals. Before you deploy some “black magic BI”, because that’s what the big companies are doing, there are some simple things you can do to get valuable information from your data.&lt;br /&gt;&lt;br /&gt;Assuming your data is in one place, you can create reports using standard SQL that will benefit your company and make them more competitive. To help with that, I have compiled a list of relatively generic reports that most companies might/should be interested in. There is a good chance that after making these reports, the management will see that you actually have some business knowledge and might ask you for more specific reports. If that is the case, then consider the information you have delivered to be a success.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Sales&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;What is the total number of placed orders?&lt;/li&gt;&lt;li&gt;What is the total number of orders that were shipped or invoiced? - When a customer places an order it is not always the case that the products are in stock.&lt;/li&gt;&lt;li&gt;What is the total amount of money from placed orders? – Sum of order value. This can be with or without shipping costs, depends on the management.&lt;/li&gt;&lt;li&gt;What is the total amount of money from orders that were shipped or invoiced?&lt;/li&gt;&lt;li&gt;What is the total number of returned/cancelled orders?&lt;/li&gt;&lt;li&gt;What is the total amount of money that was lost from returned or cancelled orders (or credit notes)?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;These reports should be for specific period of time. For example 1,2,6 and 12 months or 1,7,14,21 and 28 days.&lt;br /&gt;You can compare this month to last month’s results or this month to the same month a year ago.&lt;br /&gt;&lt;br /&gt;These reports can also be grouped by:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Product types or product ranges&lt;/li&gt;&lt;li&gt;Geographical areas (city, country or continent)&lt;/li&gt;&lt;li&gt;Customer matrix (teenagers, elderly, soccer moms, university students..). &lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Products&lt;/b&gt; (Best Sellers)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Which products sell the most quantity?&lt;/li&gt;&lt;li&gt;Which products generate the most revenue? – (product price * quantity)&lt;/li&gt;&lt;li&gt;Which products generate the most profit? – ((product price – product cost) * quantity) – To make your business more profitable, you should invest your energy in the 20% of the products that generate 80% of the profits.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;b&gt;Customers&lt;/b&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;How many new accounts/customers do we get (each day, week, month, half year or year)?&lt;/li&gt;&lt;li&gt;Who are our best customers – that buy the most from us? - The top 20% that make 80% of the profits.&lt;/li&gt;&lt;li&gt;What is our attrition rate – the numbers of accounts/customers we lose (each day, week, month, half year or year)? - If your attrition rate is high, the sales team needs to find a lot of new people just to keep things the same.&lt;/li&gt;&lt;li&gt;What is the &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Customer_satisfaction" title="Customer satisfaction" rel="wikipedia"&gt;customer satisfaction&lt;/a&gt;? – You will probably get this from surveys or customer feedback.&lt;/li&gt;&lt;li&gt;What are the top reasons for complaints?&lt;/li&gt;&lt;li&gt;How many existing customers referred new customers to your company? – You might need to setup something to collect this data. If you send your customers to do your &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Marketing" title="Marketing" rel="wikipedia"&gt;marketing&lt;/a&gt; for you, you can save a lot of money.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Website&lt;/b&gt;&lt;br /&gt;(Some of these reports can be handled by a separate application like &lt;a href="http://www.google.com/analytics/"&gt;google analytics&lt;/a&gt;)&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Which product pages get the most views?&lt;/li&gt;&lt;li&gt;Which news/blog articles get the most views?&lt;/li&gt;&lt;li&gt;How many minutes does the user spend on the website?&lt;/li&gt;&lt;li&gt;What is the percentage of abandoned shopping carts?&lt;/li&gt;&lt;li&gt;What is the average amount of time a customer spends in the shopping cart/session?&lt;/li&gt;&lt;li&gt;Most important – What is the &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Conversion_rate" title="Conversion rate" rel="wikipedia"&gt;conversion rate&lt;/a&gt; of the visitors coming to the site and the people who purchase a product?&lt;/li&gt;&lt;li&gt;Which &lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Landing_page" title="Landing page" rel="wikipedia"&gt;landing pages&lt;/a&gt; are the most viewed?&lt;/li&gt;&lt;li&gt;Which landing pages have the highest conversion rate?&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;a href="http://dilbert.com/strips/comic/2009-03-07/" title="Dilbert.com"&gt;&lt;img src="http://dilbert.com/dyn/str_strip/000000000/00000000/0000000/000000/40000/3000/500/43544/43544.strip.gif" alt="Dilbert.com" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;br /&gt;&lt;b&gt;Final Words&lt;/b&gt;&lt;br /&gt;I genuinely hope that this list of reports will help you influence your business and your position in the company for the better.&lt;br /&gt;&lt;br /&gt;I would very much like to welcome ideas for new reports or comments on current ones if they are unclear. Your feedback is appreciated.&lt;fieldset class="zemanta-related"&gt;&lt;legend class="zemanta-related-title"&gt;Related articles by Zemanta&lt;/legend&gt;&lt;ul class="zemanta-article-ul"&gt;&lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://marklogic.blogspot.com/2009/06/re-inventing-business-intelligence.html"&gt; Re-Inventing Business Intelligence &lt;/a&gt; (marklogic.blogspot.com)&lt;/li&gt;&lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://ducknetweb.blogspot.com/2009/05/microsoft-business-intelligence-in.html"&gt; Microsoft Business Intelligence in Healthcare - The NHS Solution &lt;/a&gt; (ducknetweb.blogspot.com)&lt;/li&gt;&lt;/ul&gt;&lt;/fieldset&gt;    &lt;div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"&gt;&lt;a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/c1a94c5b-80a6-4ace-9faa-a6eb657593c9/" title="Reblog this post [with Zemanta]"&gt;&lt;img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=c1a94c5b-80a6-4ace-9faa-a6eb657593c9" alt="Reblog this post [with Zemanta]" /&gt;&lt;/a&gt;&lt;span class="zem-script more-related pretty-attribution"&gt;&lt;script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"&gt;&lt;/script&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/375697951860081841-7799864616426713200?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/7799864616426713200/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=7799864616426713200" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/7799864616426713200?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/7799864616426713200?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/06/business-intelligence-for-people.html" title="Business Intelligence for the People" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;CEUFRXw_fyp7ImA9WxJUE0g.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-8527284256041662285</id><published>2009-06-14T21:01:00.008+08:00</published><updated>2009-07-12T06:43:34.247+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-12T06:43:34.247+08:00</app:edited><title>Tired of Youtube? Try the hacked version</title><content type="html">&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap; "&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;Tired of not watching the latest&lt;/span&gt;&lt;/span&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt; music videos on &lt;a href="http://www.youtube.com/"&gt;youtube&lt;/a&gt; like the way you used to before? Frustrated at the live performance or unplugged version of the song you wanted to hear (I actually like it that way, but anyway…)?  Well do I have a solution for you! &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;China has their own version of youtube called &lt;/span&gt;&lt;a href="http://www.youku.com/"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;YouKu&lt;/span&gt;&lt;/a&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;.&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap; "&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;We all know for a long time now that in China, they copy everything and have very little or no respect for copyright laws. This sometimes upsets us (check out &lt;a href="http://stackoverflow.com/"&gt;StackOverFlow&lt;/a&gt; vs &lt;a href="http://www.cnprog.com/"&gt;CNprog&lt;/a&gt;), but here is a chance for us to get something back.&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: left;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap; "&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="  white-space: pre-wrap; "&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;Go there and put in the search a name of a particularly famous/infamous blonde singer and see all the lost or missing music videos from youtube.  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;&lt;a href="http://www.youku.com/"&gt;&lt;img src="http://2.bp.blogspot.com/__8lgzcJRF8U/SjT1aUdm2NI/AAAAAAAAIjc/z3aV3kvg9ho/s400/youku.gif" style="display:block; margin:0px auto 10px; text-align:center;cursor:pointer; cursor:hand;width: 400px; height: 258px;" border="0" alt="" id="BLOGGER_PHOTO_ID_5347168490113915090" /&gt;&lt;/a&gt;&lt;/span&gt;&lt;/div&gt;&lt;div style="text-align: center;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="  white-space: pre-wrap; "&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;If you are lucky, you might even see full movies on it.  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;&lt;span class="Apple-style-span" style="white-space: pre-wrap;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="  white-space: pre-wrap; "&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;&lt;span class="Apple-style-span"  style="font-family:verdana;"&gt;However, it might be “a bit” slower then youtube is. Sorry.  &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;div&gt;&lt;span class="Apple-style-span"   style="font-family:-webkit-monospace;font-size:100%;"&gt;&lt;span class="Apple-style-span"  style=" white-space: pre-wrap;font-size:13px;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/span&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/375697951860081841-8527284256041662285?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/8527284256041662285/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=8527284256041662285" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/8527284256041662285?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/8527284256041662285?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/06/tired-of-youtube-try-hacked-version.html" title="Tired of Youtube? Try the hacked version" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/__8lgzcJRF8U/SjT1aUdm2NI/AAAAAAAAIjc/z3aV3kvg9ho/s72-c/youku.gif" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;D0cAQ3cyfCp7ImA9WxJVF08.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-5800757006944599980</id><published>2009-05-31T06:19:00.004+08:00</published><updated>2009-07-05T00:30:42.994+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-05T00:30:42.994+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Business logic" /><category scheme="http://www.blogger.com/atom/ns#" term="database" /><title>Caching Business Logic in the Database</title><content type="html">This is a presentation I gave at the Cloud Expo Europe in London on the 21st of May 2009.&lt;br /&gt;&lt;br /&gt;&lt;div&gt;I speak about: &lt;div&gt;&lt;blockquote&gt;&lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Cache" title="Cache" rel="wikipedia"&gt;Caching&lt;/a&gt; the results of processed data - data that had business logic applied to it - to the database to be re-used later.&lt;/blockquote&gt;&lt;br /&gt;&lt;br /&gt;&lt;object width="400" height="300"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=4918382&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1"&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=4918382&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;p&gt;&lt;a href="http://vimeo.com/4918382"&gt;Caching Business Logic in the Database&lt;/a&gt;&lt;br /&gt;&lt;/p&gt;&lt;div style="width: 425px; text-align: left;" id="__ss_1511266"&gt;&lt;object style="margin: 0px;" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cbl-124372220719-phpapp02&amp;amp;stripped_title=cbl-1511266"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=cbl-124372220719-phpapp02&amp;amp;stripped_title=cbl-1511266" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;div style="font-size: 11px; font-family: tahoma,arial; height: 26px; padding-top: 2px;"&gt;&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;fieldset class="zemanta-related"&gt;&lt;legend class="zemanta-related-title"&gt;Related articles by Zemanta&lt;/legend&gt;&lt;ul class="zemanta-article-ul"&gt;&lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://devlicio.us/blogs/derik_whittaker/archive/2009/02/28/it-is-sql-structured-query-language-not-sbql-structured-business-query-language.aspx"&gt;It is SQL (Structured Query Language) NOT SBQL (Structured Business Query Language)&lt;/a&gt; (devlicio.us)&lt;/li&gt;&lt;/ul&gt;&lt;/fieldset&gt;  &lt;div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"&gt;&lt;a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/feedfa97-f88b-4d81-9827-3b0c208b2a45/" title="Reblog this post [with Zemanta]"&gt;&lt;img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=feedfa97-f88b-4d81-9827-3b0c208b2a45" alt="Reblog this post [with Zemanta]" /&gt;&lt;/a&gt;&lt;span class="zem-script more-related pretty-attribution"&gt;&lt;script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"&gt;&lt;/script&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/375697951860081841-5800757006944599980?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/5800757006944599980/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=5800757006944599980" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/5800757006944599980?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/5800757006944599980?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/05/caching-business-logic-in-database.html" title="Caching Business Logic in the Database" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;D0UMSHo7eyp7ImA9WxJVF08.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-7185969948279655941</id><published>2009-05-07T22:45:00.003+08:00</published><updated>2009-07-05T00:34:49.403+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-05T00:34:49.403+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cache" /><category scheme="http://www.blogger.com/atom/ns#" term="Databases" /><title>I Will be Speaking at the Cloud Computing Expo</title><content type="html">As the title says, I will be speaking at the &lt;a href="http://www.cloudexpoeurope.com/Conference-Sessions/Technical-Track"&gt;Cloud Computing Expo&lt;/a&gt;.&lt;div&gt;And while I have &lt;a href="http://mysqlbarbeque.blogspot.com/2009/03/speeding-up-mysql-for-website.html"&gt;spoken before&lt;/a&gt; to a bunch of people before, this is by far, a lot bigger.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The topics I was thinking of talking about was a piece from my previous presentation which would be about speeding up MySQL for a web site developers.&lt;/div&gt;&lt;div&gt;I have edited those parts of the presentation and uploaded then to youtube.&lt;/div&gt;&lt;div&gt;They can be found &lt;a href="http://www.youtube.com/watch?v=b1qFbi4lPVQ"&gt;here&lt;/a&gt; and &lt;a href="http://www.youtube.com/watch?v=Wie4TgHZPiw"&gt;here&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What I'd like to talk about is a mixture of the posts I had about &lt;a href="http://mysqlbarbeque.blogspot.com/2008/08/storing-conditions.html"&gt;Storing Conditions&lt;/a&gt; and &lt;a href="http://mysqlbarbeque.blogspot.com/2008/02/using-business-rules-in-mysql-overview.html"&gt;Using Business Rules in MySQL&lt;/a&gt;. The idea, as a friend of mine put it is "&lt;a class="zem_slink" href="http://en.wikipedia.org/wiki/Cache" title="Cache" rel="wikipedia"&gt;Caching&lt;/a&gt; of Logic" in the database in order to save reprocessing data.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I hope that I am not very vague and I guess that I will need to make it clearer. But for now, I will start preparing the presentation (and I am quite excited about it).&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;fieldset class="zemanta-related"&gt;&lt;legend class="zemanta-related-title"&gt;Related articles by Zemanta&lt;/legend&gt;&lt;ul class="zemanta-article-ul"&gt;&lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://aws.typepad.com/aws/2009/02/executive-briefing-on-cloud-computing.html"&gt;Executive Briefing on Cloud Computing&lt;/a&gt; (aws.typepad.com)&lt;/li&gt;&lt;/ul&gt;&lt;/fieldset&gt;  &lt;div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"&gt;&lt;a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/3ebb9194-46fb-4fc4-baa4-cbfb4c8dcee6/" title="Reblog this post [with Zemanta]"&gt;&lt;img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=3ebb9194-46fb-4fc4-baa4-cbfb4c8dcee6" alt="Reblog this post [with Zemanta]" /&gt;&lt;/a&gt;&lt;span class="zem-script more-related pretty-attribution"&gt;&lt;script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"&gt;&lt;/script&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/375697951860081841-7185969948279655941?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/7185969948279655941/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=7185969948279655941" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/7185969948279655941?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/7185969948279655941?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/05/i-will-be-speaking-at-cloud-computing.html" title="I Will be Speaking at the Cloud Computing Expo" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;D0MFR3s4eCp7ImA9WxJVF08.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-1512184577965010387</id><published>2009-04-17T09:00:00.003+08:00</published><updated>2009-07-05T00:36:56.530+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-05T00:36:56.530+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MySQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Replication" /><title>Slave Replication Errors</title><content type="html">&lt;p class="MsoNormal"&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;I had a problem with slave replication, every now and then we would get an error which manually had to be resolved&lt;/p&gt;&lt;p class="MsoNormal"&gt;We used &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Set Global sql_slave_skip_counter = 1; start slave;&lt;/span&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;You might also get some of those when you set up a new slave using a mysqldump. If from the time you started the mysqldump and by the time it finished, some lines were added to the bin logs or you started it at the wrong position, then you would get some duplication errors. &lt;/p&gt;&lt;p class="MsoNormal"&gt;While it looks concerning, don’t panic. You can fix it by skipping the lines that are duplicates, although it’s not an ideal situation.&lt;/p&gt;&lt;p class="MsoNormal"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p class="MsoNormal"&gt;Now if you want to completely avoid errors, or specifically duplicates and you are sure that the odd ones that come along are not important, then why not try &lt;a href="http://dev.mysql.com/doc/refman/5.0/en/replication-options-slave.html"&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;log-slave-errors=1062&lt;/span&gt;&lt;/a&gt; . Even better, you can set it to “&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;all&lt;/span&gt;” and be completely oblivious to any problem that comes along.&lt;/p&gt;&lt;p class="MsoNormal"&gt;Every now and then you can check the log errors and if there are too many problems, get a new mysqldump to re-sync the slave.&lt;/p&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;p&gt;&lt;/p&gt;&lt;fieldset class="zemanta-related"&gt;&lt;legend class="zemanta-related-title"&gt;Related articles by Zemanta&lt;/legend&gt;&lt;ul class="zemanta-article-ul"&gt;&lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://mysqlha.blogspot.com/2009/04/making-replication-more-robust.html"&gt; Making replication more robust &lt;/a&gt; (mysqlha.blogspot.com)&lt;/li&gt;&lt;/ul&gt;&lt;/fieldset&gt;  &lt;div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"&gt;&lt;a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/7a087094-162d-4b79-9bfa-3a2fd4744d92/" title="Reblog this post [with Zemanta]"&gt;&lt;img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=7a087094-162d-4b79-9bfa-3a2fd4744d92" alt="Reblog this post [with Zemanta]" /&gt;&lt;/a&gt;&lt;span class="zem-script more-related pretty-attribution"&gt;&lt;script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"&gt;&lt;/script&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/375697951860081841-1512184577965010387?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/1512184577965010387/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=1512184577965010387" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1512184577965010387?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1512184577965010387?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/04/slave-replication-errors.html" title="Slave Replication Errors" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total></entry><entry gd:etag="W/&quot;D0MMRHwycCp7ImA9WxJVF08.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-6074933771128403756</id><published>2009-03-15T22:41:00.006+08:00</published><updated>2009-07-05T00:38:05.298+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-05T00:38:05.298+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MySQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Website Developers" /><category scheme="http://www.blogger.com/atom/ns#" term="Speed Up" /><title>Speeding Up MySQL for Website Developers</title><content type="html">I gave a presentation for &lt;a class="zem_slink" href="http://php.net/" title="PHP" rel="homepage"&gt;PHP&lt;/a&gt; West Midlands (UK) about how to speed up &lt;a class="zem_slink" href="http://www.mysql.com" title="MySQL" rel="homepage"&gt;MySQL&lt;/a&gt; for people who are primarily website developers.&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now the audio for the presentation could have been better. I speak very fast for some reason. I am foreign, so I have an accent. And to top it all off, I have some mistakes here and there.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If this still hasn't discouraged you, please watch the video&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;object width="400" height="300"&gt;&lt;param name="allowfullscreen" value="true"&gt;&lt;param name="allowscriptaccess" value="always"&gt;&lt;param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=5030466&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1"&gt;&lt;embed src="http://vimeo.com/moogaloop.swf?clip_id=5030466&amp;amp;server=vimeo.com&amp;amp;show_title=1&amp;amp;show_byline=1&amp;amp;show_portrait=0&amp;amp;color=&amp;amp;fullscreen=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="400" height="300"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;p&gt;&lt;/p&gt;&lt;br /&gt;&lt;div style="width: 425px; text-align: left;" id="__ss_1512415"&gt;&lt;object style="margin: 0px;" width="425" height="355"&gt;&lt;param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=thequickandeasyguidetospeedingupmysql-090531064406-phpapp01&amp;amp;stripped_title=the-quick-and-easy-guide-to-speeding-up-my-sql"&gt;&lt;param name="allowFullScreen" value="true"&gt;&lt;param name="allowScriptAccess" value="always"&gt;&lt;embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=thequickandeasyguidetospeedingupmysql-090531064406-phpapp01&amp;amp;stripped_title=the-quick-and-easy-guide-to-speeding-up-my-sql" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"&gt;&lt;/embed&gt;&lt;/object&gt;&lt;/div&gt;&lt;fieldset class="zemanta-related"&gt;&lt;legend class="zemanta-related-title"&gt;Related articles by Zemanta&lt;/legend&gt;&lt;ul class="zemanta-article-ul"&gt;&lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://oreilly.com/catalog/9780980576818/"&gt; Build Your Own Database Driven Web Site Using PHP &amp;amp; MySQL, 4th Edition &lt;/a&gt; (oreilly.com)&lt;/li&gt;&lt;/ul&gt;&lt;/fieldset&gt;  &lt;div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"&gt;&lt;a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/c2f0c54d-6dc3-481a-9662-6cd371a366d1/" title="Reblog this post [with Zemanta]"&gt;&lt;img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=c2f0c54d-6dc3-481a-9662-6cd371a366d1" alt="Reblog this post [with Zemanta]" /&gt;&lt;/a&gt;&lt;span class="zem-script more-related pretty-attribution"&gt;&lt;script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"&gt;&lt;/script&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/375697951860081841-6074933771128403756?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/6074933771128403756/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=6074933771128403756" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/6074933771128403756?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/6074933771128403756?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/03/speeding-up-mysql-for-website.html" title="Speeding Up MySQL for Website Developers" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;A0QGR3o_cSp7ImA9WxVVFE4.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-1579992960755453856</id><published>2009-03-07T08:20:00.014+08:00</published><updated>2009-03-07T23:22:06.449+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-07T23:22:06.449+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SCSI" /><category scheme="http://www.blogger.com/atom/ns#" term="Pound" /><category scheme="http://www.blogger.com/atom/ns#" term="Dell R200" /><title>Follow Up - Question of Speed and Technological Progress</title><content type="html">Well, the servers we bought (Dell R200) were in fact very cheap. &lt;div&gt;We were using 2 of them and they could not stack up to 4-5 year old servers (Dell 1750 and 1850) which have SCSI hard disks. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I added a 4 year old Dell 1850 with SCSI disks next to the 2 R200's which were all connected to a separate server running &lt;a href="http://www.apsis.ch/pound/"&gt;pound load balancer&lt;/a&gt;. The total number of maximum concurrent connections tripled.  &lt;/div&gt;&lt;div&gt;The Dell R200's cannot actually take SCSI/SAS drives (unless you go buy a proper controller). By default, they can only take Nearline-SAS which I heard is not something you would want for a web server.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I would have to say that I am putting the blame on the SATA drives. I would have thought that by now, SATA drives would be as fast as old SCSI drives, but I guess not.&lt;/div&gt;&lt;div&gt;Apart from that, I am still surprised that the new R200's with &lt;span class="Apple-style-span" style="font-weight: bold;"&gt;EIGHT&lt;/span&gt; Gbs of ram could not keep up (not even close) with much older servers.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What I'm looking into now is using &lt;a href="http://www.squid-cache.org/"&gt;squid&lt;/a&gt; for web accelerating. There is a &lt;a href="http://kevin.vanzonneveld.net/techblog/article/install_squid_apache_on_1_server/"&gt;good article&lt;/a&gt; explaining how to install it. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;While I can plainly see that the servers we chose were not amazingly fast out of the box, I'd like to believe with some tweaking and using more of the memory, they could get close to the older servers. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The final point is, that it costs man-hours to do any tweaking to the new servers. If you calculate the cost of the man-hours you would be better off just buying a faster server.&lt;/div&gt;&lt;div&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/375697951860081841-1579992960755453856?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/1579992960755453856/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=1579992960755453856" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1579992960755453856?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1579992960755453856?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/03/follow-up-question-of-speed-and.html" title="Follow Up - Question of Speed and Technological Progress" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;D0IMQnY6fip7ImA9WxJVF08.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-4776379620542221402</id><published>2009-03-04T07:04:00.006+08:00</published><updated>2009-07-05T00:39:43.816+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-05T00:39:43.816+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MySQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Master-Master Replication" /><category scheme="http://www.blogger.com/atom/ns#" term="Web server" /><title>How to Move Your Web Server With No Downtime</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://3.bp.blogspot.com/__8lgzcJRF8U/Sa26UNyXohI/AAAAAAAAIjA/4SavpI84N58/s1600-h/moving6pf-268x300.jpg"&gt;&lt;img style="margin: 0pt 10px 10px 0pt; float: left; cursor: pointer; width: 179px; height: 200px;" src="http://3.bp.blogspot.com/__8lgzcJRF8U/Sa26UNyXohI/AAAAAAAAIjA/4SavpI84N58/s200/moving6pf-268x300.jpg" alt="" id="BLOGGER_PHOTO_ID_5309104392200757778" border="0" /&gt;&lt;/a&gt;&lt;div style="text-align: left;"&gt;How do you move your web servers to another location with no downtime?&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The answer: the magic of &lt;a href="http://www.howtoforge.com/mysql_master_master_replication"&gt;MySQL Master-Master Replication&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, we are in the process of moving our web servers to another location. As usual, we would prefer to move them without anyone really noticing. What we have done is set up a skeleton of web servers in the new location as well as one database server. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now the trick is, to move without anyone knowing it AND that everything else continues working. In this example, the original location has servers that query the database if there are any new orders and process them. So it is important to keep all the parts of the system running by continually updating the database in the original location. So in this example, if you point your DNS at the new web servers and don’t update the old database, you will basically lose money.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So, what do you do?&lt;/div&gt;&lt;div&gt;Well firstly, you should set up a secure and stable connection between the two locations so that the databases can communicate with one another. &lt;a href="http://mysqlbarbeque.blogspot.com/2008/12/ssh-tunneling-between-databases-with.html"&gt;An SSH tunnel&lt;/a&gt;, will do the trick. You can set them up on the actual database server on a certain port, and it will seamlessly connect to the other database server as if it’s on your local network. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Secondly, you set up a Master/Master Active/Passive replication. This is a replication set up which is usually used for high-availability. You can also use Active/Active replication for load balancing if you take into consideration that auto-incrementing numbers would conflict on both servers. &lt;a href="http://www.howtoforge.com/mysql_master_master_replication#comment-7114"&gt;There is a solution for that as well&lt;/a&gt;.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;On the day of the move, tell your web servers from the original location to query the database in the new location through the SSH tunnel. This will slow them down, but it should be only for a few moments.&lt;/div&gt;&lt;div&gt;Change the DNS to point to the new web servers and that they are pointing to the new database server.&lt;/div&gt;&lt;div&gt;Now you have your web servers in your new location and all the other servers and services running from the updated database in your old location. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;All that’s left is to move the other servers and complete the entire move. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Job well done! You have completed the move with (hopefully) no downtime and no orders were lost. Your boss(es) will definitely be pleased with you.&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;fieldset class="zemanta-related"&gt;&lt;legend class="zemanta-related-title"&gt;Related articles by Zemanta&lt;/legend&gt;&lt;ul class="zemanta-article-ul"&gt;&lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://blog.solutionset.com/wpmu/2009/04/08/scaling-mysql-in-the-web-environment/"&gt; Scaling MySQL in the Web Environment &lt;/a&gt; (solutionset.com)&lt;/li&gt;&lt;li class="zemanta-article-ul-li"&gt;&lt;a href="http://blog.caucho.com/?p=168"&gt;Load balanced database connection pools&lt;/a&gt; (caucho.com)&lt;/li&gt;&lt;/ul&gt;&lt;/fieldset&gt;  &lt;div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"&gt;&lt;a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/eadc298e-3463-4384-b447-2ac8195f6434/" title="Reblog this post [with Zemanta]"&gt;&lt;img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=eadc298e-3463-4384-b447-2ac8195f6434" alt="Reblog this post [with Zemanta]" /&gt;&lt;/a&gt;&lt;span class="zem-script more-related pretty-attribution"&gt;&lt;script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"&gt;&lt;/script&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/375697951860081841-4776379620542221402?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/4776379620542221402/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=4776379620542221402" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/4776379620542221402?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/4776379620542221402?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/03/how-to-move-your-web-server-with-no.html" title="How to Move Your Web Server With No Downtime" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://3.bp.blogspot.com/__8lgzcJRF8U/Sa26UNyXohI/AAAAAAAAIjA/4SavpI84N58/s72-c/moving6pf-268x300.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;AkAFSXczcSp7ImA9WxVVFE4.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-7180139525830489804</id><published>2009-03-01T09:41:00.008+08:00</published><updated>2009-03-07T23:11:58.989+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-07T23:11:58.989+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Dell R200" /><category scheme="http://www.blogger.com/atom/ns#" term="TMPFS" /><title>A Question of Speed and Technological Progress</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://2.bp.blogspot.com/__8lgzcJRF8U/SansTjWseyI/AAAAAAAAIiQ/8dHi-Mu-u9U/s1600-h/500_1185305951_19108619.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 200px; height: 150px;" src="http://2.bp.blogspot.com/__8lgzcJRF8U/SansTjWseyI/AAAAAAAAIiQ/8dHi-Mu-u9U/s200/500_1185305951_19108619.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5308033456484940578" /&gt;&lt;/a&gt;&lt;div&gt;&lt;a href="http://mysqlbarbeque.blogspot.com/2009/03/follow-up-question-of-speed-and.html"&gt;Follow up post to this one&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;At my company, we have some really old web servers that host our website. They are from late 2004 and early 2005. Now, at the time, I am sure they were quite expensive.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Recently, we wanted to move to newer web servers and we bought the basic Dell R200 rack servers. Now, arguably they are quite cheap, but thinking about it they will definitely be faster then 4 year old servers, right? &lt;/div&gt;&lt;div&gt;Well, that’s what my predecessor thought when he bought those servers and I myself didn’t think about it till we wanted to start using them. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;We noticed that the new servers are at least twice as slow as old servers and that just completely baffled us. No one saw it coming. I mean, the old servers are optimized and tweaked and the new servers just have an un-tweaked but clean install of Ubuntu server with apache. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So what’s going on exactly? How is it that when hardware is so cheap and supposedly so fast, that we now have to spend some time going into configurations, messing around with things, benchmarking and basically spending man hours on something that is supposed to be quite basic. I mean, I even used my cure-all method and threw some memory at the new servers to get them to 8Gb and it still didn’t work.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, so now we have to start spending time on speeding up the servers. Things that have been suggested were:&lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Removing un-needed modules or parts from the linux kernel and recompiling it. Although, I’m not too thrilled about that.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Tweaking Apache Config&lt;br /&gt;&lt;/li&gt;&lt;li&gt;And my suggestion which was put everything in memory with TMPFS. Again, I like memory, I’m from a MySQL background.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;From my experience, PHP isn’t usually the bottleneck. So I need to look at the whole puzzle to see where the bottlenecks are. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;For my part, I have looked at the MySQL server and we also monitor it with Nagios. I am not seeing any particular slowness from it and Nagios isn’t telling me that its being overused, but I guess I could still run some benchmarks on it. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Anyway, it’s a big mystery to us why it is as slow as it is compared to some 4 year old servers. Granted, the servers we have now are quite inexpensive, but we are still very surprised.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Moore`s law doesn't apply to web servers and cheap hardware will always be cheap.  &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I’ll leave some links that I found recently and we will try to use them to speed up the web servers. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Slashdot Effect&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.linuxformat.co.uk/pdfs/download.php?PDF=LXF97.slashdot.pdf"&gt;http://www.linuxformat.co.uk/pdfs/download.php?PDF=LXF97.slashdot.pdf&lt;/a&gt;&lt;/div&gt;&lt;div&gt;Apache Tweaks&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.askapache.com/htaccess/apache-web-server-speed-configuration-hacks.html"&gt;http://www.askapache.com/htaccess/apache-web-server-speed-configuration-hacks.html&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;TMPFS – Linux Memory Partition&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.howtoforge.com/storing-files-directories-in-memory-with-tmpfs"&gt;http://www.howtoforge.com/storing-files-directories-in-memory-with-tmpfs&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://kevin.vanzonneveld.net/techblog/article/create_turbocharged_storage_using_tmpfs/"&gt;http://kevin.vanzonneveld.net/techblog/article/create_turbocharged_storage_using_tmpfs/&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://mysqlbarbeque.blogspot.com/2009/03/follow-up-question-of-speed-and.html"&gt;Follow up post to this one&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&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/375697951860081841-7180139525830489804?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/7180139525830489804/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=7180139525830489804" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/7180139525830489804?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/7180139525830489804?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/03/question-of-speed-and-technological.html" title="A Question of Speed and Technological Progress" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://2.bp.blogspot.com/__8lgzcJRF8U/SansTjWseyI/AAAAAAAAIiQ/8dHi-Mu-u9U/s72-c/500_1185305951_19108619.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;A0QEQHk6fCp7ImA9WxVVFE4.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-1741476656951473393</id><published>2009-01-28T08:47:00.008+08:00</published><updated>2009-03-07T23:21:41.714+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-07T23:21:41.714+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term=".NET" /><category scheme="http://www.blogger.com/atom/ns#" term="Microsoft" /><title>What the ‘Microsoft’?!</title><content type="html">&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://4.bp.blogspot.com/__8lgzcJRF8U/SX-rj2ELNUI/AAAAAAAAIhU/BF1VSL0O1Xk/s1600-h/frustrated_with_computer.jpg"&gt;&lt;img style="float:right; margin:0 0 10px 10px;cursor:pointer; cursor:hand;width: 239px; height: 159px;" src="http://4.bp.blogspot.com/__8lgzcJRF8U/SX-rj2ELNUI/AAAAAAAAIhU/BF1VSL0O1Xk/s400/frustrated_with_computer.jpg" border="0" alt="" id="BLOGGER_PHOTO_ID_5296140319107790146" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div&gt;I’ve had about enough of Microsoft and its approach to help small businesses develop application. The .NET platform is FAR FAR from ‘working everywhere’ and being compatible to everything. Let me write down some points to what I mean.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Windows Applications that are developed in Visual Studio.NET by SMBs usually (almost always):&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Do not work on other machines, even when its .NET.  Don’t assume a .NET application will work on every machine. You need an installation of visual studio for &lt;span class="Apple-style-span" style="font-style: italic;"&gt;each&lt;/span&gt; machine you want your application to work on.&lt;/li&gt;&lt;li&gt;Do not work with Crystal Reports. It might work “ok” on your computer, but if/when it doesn’t print on someone else’s machine, try to find some support.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Stop working when you update windows. Update at your own risk&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Randomly disconnects from the network or has DNS problems. From the words of my system administrator “its being windows”.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Randomly doesn’t connect to the database. See above.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Locks up the database with all the open connections. That’s what happens when you distribute fat clients to everyone.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Crashes when some windows services mysteriously stop working.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Have issues when being deployed and make you click 10 ‘OK’ buttons just to open it. I do not know why, but someone previously decided to have a shared network drive with the .NET files on it, so that we can update one place and everyone goes there to run it (every single time). But try as they might, they still needed to put some config files on each machine.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Have a low learning curve which lets idiots make decisions on software architecture which afterwards are too complicated to change. &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;My personal opinion is that the Microsoft lock-in, is the problem. It starts off with &lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;Oh yes, its so comfy and easy using Excel sheets&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Oh.. lets write some functions using my macros&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Now lets try some VBA/VB6&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Hmm… we need a database… oh.. lets use Access.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;(A year goes by….)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Hmm.. we need something more serious, we have more people using our system…. lets call someone and ask what we need…&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Salesman: “yes, what you need is first of all 2 Windows servers, one with a domain controller/Active Directory and one with MS SQL database. Then you will need lots of CALs (licenses). If you are already there, you might as well use Exchange too. Then you need 2-3 copies of Visual Studio.NET team edition for your small development team. You know what?.. I think you will need a BizTalk server as well, just to be on the safe side. Oh.. and finally, installation and maintenance fees will come to ££££££££££££££££££!”. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;Managing Director *gulp*.&lt;br /&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Maybe nowadays this scenario may not be so common and more people would be happy cutting down costs. Perhaps by using MySQL instead of MS SQL. However, then you have interfered with the natural order of the way Microsoft wants things to be.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I don’t know, obviously this is a rant because I’m frustrated about some things. I guess I am glad &lt;a href="http://mysqlbarbeque.blogspot.com/2009/01/developing-internal-business.html"&gt;I decided to do something about it&lt;/a&gt;.&lt;/div&gt;&lt;div&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/375697951860081841-1741476656951473393?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/1741476656951473393/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=1741476656951473393" title="5 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1741476656951473393?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1741476656951473393?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/01/what-microsoft.html" title="What the ‘Microsoft’?!" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="http://4.bp.blogspot.com/__8lgzcJRF8U/SX-rj2ELNUI/AAAAAAAAIhU/BF1VSL0O1Xk/s72-c/frustrated_with_computer.jpg" height="72" width="72" /><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">5</thr:total></entry><entry gd:etag="W/&quot;D0AEQ306fyp7ImA9WxJVF08.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-1528452718258131140</id><published>2009-01-19T01:50:00.008+08:00</published><updated>2009-07-05T00:41:42.317+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-07-05T00:41:42.317+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Cache" /><category scheme="http://www.blogger.com/atom/ns#" term="Website" /><title>Caching and Actually Speeding Things Up</title><content type="html">&lt;div&gt;I've ran into many people throughout my career that were under the impression that caching is a cure for cancer, world hunger and global warming. I myself often fall pray to the "just add more memory" approach for solving problems. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Some 5 years ago, while I was working with ASP classic and VB 6 (yes, you are allowed to chuckle now) on my online movie collection, I came up with the idea that nothing actually beats a flat and pre-processed HTML file for speed. I mean, this may seem obvious and no matter how many times I tried to add cache and do all sorts of tricks, nothing would beat a static file. The problem here is that when I suggest this sort of solution, people would almost always answer that "well, we have caching anyway" and that this sort of solution would actually be going backwards.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now granted, you cannot use static files for most dynamic pages (static != dynamic) and maybe this would never be a real long-term solution, however lets just consider these &lt;a href="http://www.avnetlabs.com/php/php-framework-comparison-benchmarks"&gt;benchmarks for PHP and Ruby Frameworks&lt;/a&gt;. No matter how many different types of caches you apply to your framework, you will never actually beat HTML files or baseline PHP files for that matter. But the point is, that going back to basics beats frameworks by an order of magnitude. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This reminded me of something I wrote a loooong time ago about&lt;a href="http://mysqlbarbeque.blogspot.com/2007/11/exploring-event-driven-publishing.html"&gt; event-driven publishing&lt;/a&gt;, when something is updated in the database, the webpage cache of a website gets regenerated.&lt;br /&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;&lt;div&gt;This also reminded me about my thoughts about &lt;a href="http://mysqlbarbeque.blogspot.com/2008/08/storing-conditions.html"&gt;storing conditions in database tables&lt;/a&gt;, where you can save pre-processed results to the database to save you re-processing them. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Well, not so much a conclusion, but an option. Consider making the parts of your website that do not change very often, into static files if you are very concerned about speed. Have your system generate these static files every time they need to be updated.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;  &lt;div style="margin-top: 10px; height: 15px;" class="zemanta-pixie"&gt;&lt;a class="zemanta-pixie-a" href="http://reblog.zemanta.com/zemified/553e1dd1-5b97-45b7-806f-9ef73fe4ee8e/" title="Reblog this post [with Zemanta]"&gt;&lt;img style="border: medium none ; float: right;" class="zemanta-pixie-img" src="http://img.zemanta.com/reblog_e.png?x-id=553e1dd1-5b97-45b7-806f-9ef73fe4ee8e" alt="Reblog this post [with Zemanta]" /&gt;&lt;/a&gt;&lt;span class="zem-script more-related pretty-attribution"&gt;&lt;script type="text/javascript" src="http://static.zemanta.com/readside/loader.js" defer="defer"&gt;&lt;/script&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/375697951860081841-1528452718258131140?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/1528452718258131140/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=1528452718258131140" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1528452718258131140?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1528452718258131140?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/01/caching-and-actually-speeding-things-up.html" title="Caching and Actually Speeding Things Up" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0YDSX85eyp7ImA9WxVSF0s.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-3812637649859655289</id><published>2009-01-12T21:44:00.003+08:00</published><updated>2009-01-12T22:06:18.123+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-01-12T22:06:18.123+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="PHP" /><category scheme="http://www.blogger.com/atom/ns#" term="Business Applications" /><title>Developing Internal Business Applications with PHP</title><content type="html">Recently, my company has decided to go full (or mostly) open source by moving away from Microsoft technologies. This is a particularly exciting venture to be part of, but in order to explain what I mean, I need to go back a bit and explain the history of the company.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;History&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Since its inception, the company has been a traditional LAMP stack. Over time, some internal business applications were needed to be developed. The initial platform to solve this requirement was Microsoft Office and specifically Access database and some Excel sheets. Later on, more and more VBA programming was added to the Access database. At some stage, a decision was made to move to VB.NET and port the VBA/VB6 code to it.&lt;br /&gt;So far, this story is not that unique and I am sure many of you reading this can either relate to it or know of examples from other places.&lt;br /&gt;&lt;br /&gt;There were issues moving to VB.NET from the start. It took over a year to finally move to it with many complications and a lot of resources invested in it during that time. After some time, the resources depleted and 1 developer was left to maintain the system.&lt;br /&gt;With time, the application stagnated and the 1 developer could not keep up with the bugs and requirements for new features.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Present&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;At this stage I came into the company and I decided that some serious work had to be done to improve the internal business application. I had made a plan to fix and improve the existing code base but saw that it would take a considerable amount of time and energy as well as expertise that we did not have.&lt;br /&gt;At this point, I took a look at other parts of the company. The company has a very good history with open source products. The relatively new PHP team was accomplishing quite a lot of things. All the servers are on various flavours of Linux and maintained well.&lt;br /&gt;&lt;br /&gt;The only parts that were holding the company back were closed source technologies. Specifically, incompatibilities between 3rd party applications, printers and forced networking standards that come with closed source. The cost for .NET developers was also an issue.&lt;br /&gt;It seemed to me that the culture of the company is more aligned with open-source and ultimately, that would be the direction the company should follow. The only problem was that, because of initial convenient and easy-to-use application, the company was locked in to a now costly and constricted system.&lt;br /&gt;&lt;br /&gt;The system that was chosen was PHP. From one point of view, PHP was the obvious choice, considering the expertise the company has. From another point of view, selecting a web-based technology to replace fat clients with rich GUI, isn’t the most obvious choice.&lt;br /&gt;Considering all the different points (and after being grilled by the executives a bit), the decision was made mainly because of our strong history, achievements and expertise with PHP and Linux. The difficulties that PHP might have to replace the VB.NET system were researched and solutions were offered.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The Official Reasons to Move to PHP from VB.NET&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;To cut down costs and unify technical support expertise. It is difficult and costly to support multiple systems technologies.&lt;/li&gt;&lt;li&gt;To reduce complexity and speed up development time. The company has had a lot of success delivering products and features with PHP and believes that this success can be replicated for the internal business application.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Full Steam Ahead&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;When making this system it is very important to make sure that the system will be very stable, maintainable and flexible for future changes. It would need to prove that it can overcome the difficulties that the old system had troubles facing. After that, development speed is crucial as all new features will have to be put on hold until all the system (or at least some parts of it) is rewritten.&lt;br /&gt;&lt;br /&gt;So the important factors were the quality and flexibility of the code as well as speed of development. I decided that in order to achieve these goals, we would need to use frameworks, tools, add-ons and coding standards. The idea is to leverage existing open-source products and best practices to save time and ensure quality. It is also important to make sure that by using the same tools and following the same coding standards, the code will be maintainable for many years to come.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The List of Technologies&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I have compiled a detailed list of technologies, open-source products, frameworks, tools and coding standards we plan to use to get this project done properly. All of these are supposed to lay the foundation for a rigid and structured development process.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;ul&gt;&lt;li&gt;LAMP Stack - &lt;a href="http://www.php.net/"&gt;PHP 5&lt;/a&gt;, &lt;a href="http://dev.mysql.com/downloads/mysql/5.1.html"&gt;MySQL 5.1&lt;/a&gt;  – for improved replication and partitioning, &lt;a href="http://www.ubuntu.com/products/whatIsubuntu/serveredition"&gt;Ubuntu Server &lt;/a&gt; and &lt;a href="http://httpd.apache.org/"&gt;Apache Web Server &lt;/a&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://framework.zend.com/"&gt;Zend framework&lt;/a&gt; – This is something the company has chosen a long time ago and it’s something we plan to continue with.&lt;/li&gt;&lt;li&gt;&lt;a href="http://uk.php.net/apc"&gt;APC&lt;/a&gt;  – &lt;a href="http://en.wikipedia.org/wiki/PHP_accelerator"&gt;PHP accelerating&lt;/a&gt; to speed up bootstrapping.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.danga.com/memcached/"&gt;Memcached&lt;/a&gt; – To speed up database interactions. We came to the conclusion that memcached sped our whole system by a factor of 40.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.doctrine-project.org/"&gt;Doctrine&lt;/a&gt; ORM – I didn’t want us to spend a second of a developers time on mapping database tables to classes, so I wanted an ORM. Doctrine seemed to have a better website then Propel, so we chose that. So it’s literally a case of judging a book by its cover.&lt;/li&gt;&lt;li&gt;&lt;a href="http://developer.yahoo.com/yui/"&gt;YahooUI&lt;/a&gt; Javascript Framework – After my developers being biased to &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; and I was biased for &lt;a href="http://www.extjs.com/"&gt;ExtJS&lt;/a&gt;, we decided to choose YahooUI as it was somewhat close to the rich GUI that our VB.NET uses now. We chose this framework to try to keep javascript development to as low as possible by using already made widgets and libraries from the framework.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.phpunit.de/"&gt;PHPUnit&lt;/a&gt;  – This is one of the important parts of the foundation we need to start building the new system. If we cannot have some guarantee that the system is stable then what is the point of the whole thing.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.phpundercontrol.org/"&gt;phpUnderControl&lt;/a&gt; with &lt;a href="http://cruisecontrol.sourceforge.net/"&gt;CruiseControl&lt;/a&gt; (Continuous integration server) – “&lt;a href="http://en.wikipedia.org/wiki/Continuous_integration"&gt;Continuous integration&lt;/a&gt; describes a set of software engineering practices that speed up the delivery of software by decreasing integration times”. phpUnderControl uses PHPUnit, &lt;a href="http://www.phpdoc.org/"&gt;PHPDocumentor&lt;/a&gt;, &lt;a href="http://pmd.sourceforge.net/"&gt;PMD&lt;/a&gt;, &lt;a href="http://pear.php.net/package/PHP_CodeSniffer"&gt;PHP_CodeSniffer&lt;/a&gt; and &lt;a href="http://checkstyle.sourceforge.net/"&gt;CheckStyle&lt;/a&gt;.&lt;/li&gt;&lt;li&gt;&lt;a href="http://subversion.tigris.org/"&gt;Subversion&lt;/a&gt; SCM – We obviously, need source control management and we are already familiar with subversion. We had considered &lt;a href="http://git-scm.com/"&gt;Git&lt;/a&gt;, but didn’t choose it in the end.&lt;/li&gt;&lt;li&gt;&lt;a href="http://framework.zend.com/manual/en/coding-standard.coding-style.html"&gt;Zend Coding Style&lt;/a&gt; – The development team decided that in order to organize and standardize their code, they want to use the Zend Coding style. I also understood that it will later help with phpUnderControl with its style checking.&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Scrum_%28development%29"&gt;Scrum&lt;/a&gt; with &lt;a href="http://www.danube.com/scrumworks"&gt;ScrumWorks&lt;/a&gt; – We use Scrum and we find it very effective. The application we use for it is ScrumWorks Basic. Even though we don’t think it’s the best one, it works for most cases and is quite convenient.&lt;/li&gt;&lt;li&gt;&lt;a href="http://seleniumhq.org/"&gt;Selenium&lt;/a&gt; with &lt;a href="http://www.phpunit.de/manual/3.1/en/selenium.html"&gt;PHPUnit extension&lt;/a&gt; – for front-end testing. Selenium can test front end pages/forms and javascript functionality. Selenium can be called from PHPUnit which will fit with the automated testing suite.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.extremeprogramming.org/rules/userstories.html"&gt;Acceptance Testing for our User Stories&lt;/a&gt; – This is a standard we liked. We like to specify with the user stories the acceptance test or success criteria for this user story to be considered done.&lt;/li&gt;&lt;li&gt;&lt;a href="http://mikebernat.com/blog/MVC_-_Fat_Models_and_Skinny_Controllers_"&gt;Fat-Models, Skinny Controllers&lt;/a&gt; – A standard we are all in agreement is a very good practice.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.phpunit.de/manual/3.1/en/other-uses-for-tests.html"&gt;PHPUnit TestDox&lt;/a&gt; for documentation - I wanted the tests to be the actual documentation. All the requirements and behaviors of the system should be the actual tests of the system. PHPUnit has a way to extract the test name and generate documentation for them. We will also use PHPDocumentor and &lt;a href="http://www.dokuwiki.org/"&gt;Dokuwiki&lt;/a&gt; for anything else.&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/SOAP_%28protocol%29"&gt;SOAP&lt;/a&gt;/&lt;a href="http://en.wikipedia.org/wiki/Representational_State_Transfer"&gt;REST&lt;/a&gt;– We will use SOAP/REST for any component that might need to be called from another location. With all the talk about &lt;a href="http://en.wikipedia.org/wiki/Service-Oriented_Architecture"&gt;SOA&lt;/a&gt;, I decided to just implement the minimum use of it, which is to use it when other locations need to use this functionality. This is instead of having the code in 2 places and both try to get data from the same database as the point of integration.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.mozilla.com/firefox/"&gt;FireFox&lt;/a&gt;/&lt;a href="https://developer.mozilla.org/en/Prism"&gt;Prism&lt;/a&gt; - We can dictate which default browser we plan to support. Prism is also quite a cool application to make our application look like… a real application.&lt;/li&gt;&lt;li&gt;Validations for HTML and CSS – Even though we don’t need to make our internal business application &lt;a href="http://en.wikipedia.org/wiki/Search_engine_optimization"&gt;SEO&lt;/a&gt; friendly, it still might be a good idea to run some validation on it.&lt;/li&gt;&lt;li&gt;&lt;a href="http://en.wikipedia.org/wiki/Lightweight_Directory_Access_Protocol"&gt;LDAP&lt;/a&gt; (linux) - We though it might be a good idea to have this for user logging and authentication, but the brightest idea would be that we would then know which printer is closest to that user.&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.blogger.com/%28http://www.nagios.org/"&gt;Nagios&lt;/a&gt; for &lt;a href="http://www.mydigitallife.info/2006/09/23/monitor-and-check-web-site-or-server-uptime-and-availability-for-free/"&gt;Web Page monitoring&lt;/a&gt; – We can monitor if the website is up and get advanced warning if something is wrong.&lt;/li&gt;&lt;li&gt;&lt;a href="http://incubator.apache.org/log4php/"&gt;Log4php&lt;/a&gt; – a ready made logging library ported from java.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;We are all quite pleased about the decision and look forward to start working on this project. I hope to learn as much as I can from this experience and I am sure the development team feels the same way.&lt;br /&gt;I strongly believe that PHP with the addition of other open source products can deliver the same if not better results then VB.NET/ASP.NET would and I plan to put my money where my mouth is.&lt;br /&gt;&lt;br /&gt;For writing this article, I did some research into Enterprise PHP, but did not find too many (current) articles about them. I hope to start seeing a bigger trend towards Enterprise PHP applications&lt;br /&gt;I will keep bloging about the project when interesting things come up and I keep the right to update the list I made in case we decide that some parts of it are not as good as we thought&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/375697951860081841-3812637649859655289?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/3812637649859655289/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=3812637649859655289" title="9 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/3812637649859655289?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/3812637649859655289?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2009/01/developing-internal-business.html" title="Developing Internal Business Applications with PHP" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">9</thr:total></entry><entry gd:etag="W/&quot;AkcDRH47eyp7ImA9WxVTF04.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-158329619524730741</id><published>2008-12-31T23:16:00.003+08:00</published><updated>2008-12-31T23:41:15.003+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-31T23:41:15.003+08:00</app:edited><title>New Year's Resolution</title><content type="html">Its been a while since I blogged.. and my new year's resolution would be to blog more.&lt;div&gt;&lt;ul&gt;&lt;li&gt;I could say that I have been very busy at work. I can't really say that I haven't been using MySQL, since I've been using it more these days than I have in my entire career.&lt;/li&gt;&lt;li&gt;I could say that I am noticing a trend to blog less in the MySQL community. I could be wrong about that, but I definitely don't see the same names blogging as the ones I used to see a year ago. But that could be that some people just moved on.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I could say that I have just been lazy. My blog statistics certainly reflect that.&lt;/li&gt;&lt;li&gt;Finally, I could say that I lost a bit of enthusiasm for blogging about MySQL. This could be that my priorities have shifted slightly, but I plan to get myself a bit more involved with database developing/administrating in the very near future.&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;Other things on my list for the new year is:&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;Re-learn the PHP that I forgot&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Learn Subversion branching&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Learn Git&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Learn PHPUnit testing &lt;- almost done&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Learn how to use CruiseControl or PHPUnderControl&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Look into ExtJS (for a Intranet Project)&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Learn Ruby and/or Erlang in my free time......&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&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/375697951860081841-158329619524730741?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/158329619524730741/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=158329619524730741" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/158329619524730741?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/158329619524730741?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/12/new-years-resolution.html" title="New Year's Resolution" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;DEUBRXo6cCp7ImA9WxRaE00.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-6272964934183533119</id><published>2008-12-15T00:08:00.012+08:00</published><updated>2008-12-15T09:57:34.418+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-15T09:57:34.418+08:00</app:edited><title>Reporting SpeedUp Trick</title><content type="html">I've been asked to make some reports recently for some people in my company.&lt;div&gt;Almost all of them are quite heavy and hit the database pretty hard.&lt;/div&gt;&lt;div&gt;The thing is that these reports are usually generated once or twice a month, but they process a year's worth of data. Every time they are generated, they really upsets my poor production MySQL database.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I was thinking if there maybe could be a better way to just save the processed data in a table and update it every now and then.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So.. this is what I did: &lt;/div&gt;&lt;div&gt;&lt;ol&gt;&lt;li&gt;I created a table that keeps the aggregated results from the report.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I added to the start of the SQL statement "&lt;a href="http://dev.mysql.com/doc/refman/5.1/en/insert-select.html"&gt;INSERT INTO reports.thistable SELECT &lt;/a&gt;(the worlds most intensive SQL query)  ;"&lt;br /&gt;&lt;/li&gt;&lt;li&gt;At this point I realised that I need a bit extra help determining which parts of the data should be updated and which is already in the table. So I added an "last_updated" column in both tables with a &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/timestamp.html"&gt;current_timestamp&lt;/a&gt;.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;I changed the INSERT INTO statement to an &lt;a href="http://dev.mysql.com/doc/refman/5.1/en/insert.html"&gt;INSERT.. ON DUPLICATE KEY&lt;/a&gt; so it can add to the previous amount in the aggregated table. &lt;br /&gt;&lt;/li&gt;&lt;li&gt;I also made sure that I added more primary keys to the reports table so the statement will know which fields are in fact duplicate keys.&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Lastly, I added: WHERE filter the data table's timestamp column by -&gt; (SELECT the last timestamp on the reports table). So basically, you are (in theory) only getting fresh data to update into your reports table.&lt;/li&gt;&lt;/ol&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is fine for tables that only have data inserted into them. If existing rows get updated, you might need to use a trigger. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;What I plan to do is to give an option to clear the whole report table if the user doesn't trust the data. However, in the future, I will limit that query from running during certain work hours to avoid upsetting the production database.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&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/375697951860081841-6272964934183533119?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/6272964934183533119/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=6272964934183533119" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/6272964934183533119?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/6272964934183533119?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/12/reporting-speedup-trick.html" title="Reporting SpeedUp Trick" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;C0QNQ3c8cSp7ImA9WxRbGUk.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-7187987959505669729</id><published>2008-12-11T04:15:00.002+08:00</published><updated>2008-12-11T04:36:32.979+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-12-11T04:36:32.979+08:00</app:edited><title>Prepared Statements Killed My Database</title><content type="html">In two separate instances, prepared statements used up all my database's connections and completely locked it. To the point that we had to restart the mysql server and in the other case, physically reset the server (not something you usually do with linux servers).&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Apparently, one table had a read lock on it, which made the prepared statement wait a bit too long and it decided to flood the database connections till it would got an answer. Only the table was still locked and the database came to a screeching halt.&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;The last thing I saw on my screen was a bunch of the same prepared statement on my process list screen, completely taking up all the slots and then.... I lost my connection to see the process list.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I don't really understand how the perl script and php page that ran the prepared statement could be so aggressive or where was it defined to continue opening new connections till they got an answer.  &lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;This is definatly a first for me and afterwards I changed some of the tables to be more transactional, so that they wont lock.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Conclusion... well there is no conclusion. I'm not going to rule out using prepared statements, but I am going to look more into their behavior (once I find out where they are).&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&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/375697951860081841-7187987959505669729?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/7187987959505669729/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=7187987959505669729" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/7187987959505669729?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/7187987959505669729?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/12/prepared-statements-killed-my-database.html" title="Prepared Statements Killed My Database" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total></entry><entry gd:etag="W/&quot;A0QMRH06cSp7ImA9WxVVFE4.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-3052144589396641452</id><published>2008-12-04T20:32:00.005+08:00</published><updated>2009-03-07T23:23:05.319+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-07T23:23:05.319+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="SSH Tunnel" /><title>SSH Tunneling between databases with MySQL</title><content type="html">Dear Lazyweb&lt;br /&gt;&lt;br /&gt;I saw recently an interesting installation at a company. This company had databases in two different locations and they established a connection using SSH tunneling.&lt;br /&gt;&lt;br /&gt;The thing that looked very interesting to me is, they setup a dedicated machine that had a MySQL instance on it. That database was mostly empty, but it had a port open on that machine that is a "virtual" tunnel. This allowed you to connect to the databases in the second location but it seemed as if the database is local to the network.&lt;br /&gt;I believe this opens up a SSH tunnel and from my first impressions, it appears to be the case. My question is, how is that setup?&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/375697951860081841-3052144589396641452?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/3052144589396641452/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=3052144589396641452" title="3 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/3052144589396641452?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/3052144589396641452?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/12/ssh-tunneling-between-databases-with.html" title="SSH Tunneling between databases with MySQL" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">3</thr:total></entry><entry gd:etag="W/&quot;CUEFRnk8eCp7ImA9WxRUFUs.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-8518688590351471670</id><published>2008-11-25T05:42:00.003+08:00</published><updated>2008-11-25T05:53:37.770+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-25T05:53:37.770+08:00</app:edited><title>MySQL Function to Change Hard-Coded Tax, Anyone?</title><content type="html">In the UK, &lt;a href="http://news.bbc.co.uk/1/hi/uk_politics/7745340.stm"&gt;tax prices have gone down from 17.5% to 15%&lt;/a&gt; .&lt;div&gt;Good news!&lt;/div&gt;&lt;div&gt;However, its a bit of a nightmare to change the prices on our websites. We're lucky. We don't have to reprint thousands of pamphlets that have prices for Christmas sales, since we are a primarily web-based company.&lt;/div&gt;&lt;div&gt;My boss said that this is like the Y2K bug, only you have 1 week to fix it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Basically, we need to go over hundreds of pages of code for some 'very' hard-coded tax figures.&lt;/div&gt;&lt;div&gt;Our databases will also need to have a look at. I might need to have an all-encompassing function to look for products with tax already calculated into them and update them.&lt;/div&gt;&lt;div&gt;Oh well, it looks like it will be interesting.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Wish me luck.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&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/375697951860081841-8518688590351471670?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/8518688590351471670/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=8518688590351471670" title="1 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/8518688590351471670?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/8518688590351471670?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/11/mysql-function-to-change-hard-coded-tax.html" title="MySQL Function to Change Hard-Coded Tax, Anyone?" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">1</thr:total></entry><entry gd:etag="W/&quot;A0UDRHwzeip7ImA9WxVVFE4.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-2355237881583945307</id><published>2008-11-19T20:04:00.003+08:00</published><updated>2009-03-07T23:21:15.282+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-07T23:21:15.282+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Scrum" /><title>Me ScrumMaster, You Jane?</title><content type="html">Yes, I have turned into the stereotype called a scrum-master. I haven't really done the infamous 2 day course on it to be certified, but apparently I read enough about it and practiced some of the principles to know a few things (or at least to think I know).&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;In my company&lt;/span&gt;..&lt;br /&gt;&lt;br /&gt;In my company, we do use scrum with our development team. In most cases it works very well and the management are very happy. In some cases, where emergency support is involved, not so much, but they still like the structure of it and the fact that people commit to finishing things.&lt;br /&gt;&lt;br /&gt;In all cases, very little testing is being applied and almost no documentation is written. I do realize that in the case of documentation, agile is suppose to cut down on those, but some form of documentation or changing some charts will be fine by me. In the case of testing, I think since I made a fuss about it, more testing has been done. But, I still think we could do much more about testing.&lt;br /&gt;&lt;br /&gt;I spoke with my boss about it and how he looked at it was that, we had applied a process that brought in positive results and now we are at the next stage where we evaluate some of the problems that rose to the surface. Meaning, we are doing so well that we are fine tuning the process. I tend to agree with him on that. Even though technically, scrum does say that you need continuous integration testing, most places I have seen have been struggling with the testing sides of it. Oh, I did the self assessment on the &lt;a href="http://www.cedur.se/nokia_test2.html"&gt;nokia test&lt;/a&gt; and got a 5 out of 10.&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;&lt;br /&gt;Oh noes!! we must write tests now!&lt;br /&gt;&lt;/span&gt;&lt;br /&gt;To be perfectly honest, its quite difficult to sell people on the idea of testing in general. Sometimes, when I mention testing, everyone thinks I am talking about moving everyone to test-driven-development. So in any case everyone is scared I am making earth-shaking changes to the whole process they are used to.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;The (slight) Downsides of Tests&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;Tests themselves have issues that you need to maintain them. If you write a test with very specific parameters and values and then one day you change the actual behavior of the code, you will need to re-write your tests. You can avoid that by making your tests flexible for those changes, but you need to be aware and somewhat experienced in testing to do that.&lt;br /&gt;&lt;br /&gt;Also, when you develop something new, writing tests can be much more simpler then writing tests when you are trying to fix old code. That is something I am particularly struggling with, since a lot of the work we need to do is patchwork to existing code. Just to add tests to existing code means you have to go into it, understand it and then apply some tests to it.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;I need to study the issue more and try to apply it to my teams.&lt;br /&gt;In any case, we need more testing and documentation (documentation is something I also plan to write about).&lt;br /&gt;&lt;br /&gt;What I have decided to do is to try to do some of the following things:&lt;br /&gt;1) Add certain tests as a requirement on the user stories&lt;br /&gt;2) Do user stories that the whole process is to write tests for a problematic part of the code (the 20% of the code that causes 80% of the problems)&lt;br /&gt;3) Do a face-off between 2 teams. One will use TDD and the other one won't. This will be a proof of concept that TDD is faster to develop then with regular development or even it is slower, only marginally slower and has the addition of all the extra tests.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;Here are some questions I have asked on stackoverflow:&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/285933/how-do-you-apply-scrum-to-maintenance-and-legacy-code-improvements"&gt;How do you apply Scrum to maintenance and legacy code improvements?&lt;/a&gt;&lt;br /&gt;&lt;a href="http://stackoverflow.com/questions/300605/scrum-but-with-no-testing-or-documentation"&gt;Scrum, but with no testing or documentation&lt;/a&gt;&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/375697951860081841-2355237881583945307?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/2355237881583945307/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=2355237881583945307" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/2355237881583945307?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/2355237881583945307?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/11/me-scrummaster-you-jane.html" title="Me ScrumMaster, You Jane?" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0IFQHczfip7ImA9WxVVFE4.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-1982922482881146919</id><published>2008-11-11T06:49:00.005+08:00</published><updated>2009-03-07T23:25:11.986+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-07T23:25:11.986+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="Windows Vista" /><title>Can't Find New Non-Windows Machines</title><content type="html">I was looking for some non-windows machines for my development team. My development team all use Ubuntu. As hard as I tried, I couldn't really find anything pre-built that didn't have windows on it. &lt;div&gt;I really don't like the idea that I will buy machines with windows on them just to have them formatted and have linux installed over them. And what really gets me is that windows will add to the price of the machine (at time when I'm trying to cut down on all my department's spendings). &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I was considering to order computer parts and build the machines myself. But after getting flashbacks of my youth, trying to find the right CPU to fit the right motherboard, I decided that my time could be better spent on other things.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;In the end, I found that the best option would be to buy servers for my developers instead of work-stations. I found a nice 'HP ProLiant ML115 G5 AMD Opteron 1352 Quad Core'. It was extremely cheap. It comes with 512mbs of ram, but I can add up to 8gbs of memory. Which I fully intend on doing for my own work-station, because I am trying to play around with our MySQL databases on my laptop (I copied dumps to my laptop, don't worry) and it takes forever to do the tiniest alterations. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So all in all, it is a good deal, but it's not very conventional. I was kind of hoping that Dell would do something with linux work-stations, but the only thing I could find with linux (or no OS) machines was those (cute) mini-netbooks.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Conclusion&lt;/span&gt;&lt;/div&gt;&lt;div&gt;Linux Machine with 8Gbs of Ram is much better then (&gt;)  Windows Vista machines for the same price.&lt;br /&gt;&lt;/div&gt;&lt;div&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/375697951860081841-1982922482881146919?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/1982922482881146919/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=1982922482881146919" title="4 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1982922482881146919?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1982922482881146919?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/11/cant-find-new-non-windows-machines.html" title="Can't Find New Non-Windows Machines" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">4</thr:total></entry><entry gd:etag="W/&quot;DUMNQXg7cSp7ImA9WxRWFko.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-4106059775976359754</id><published>2008-11-03T09:48:00.002+08:00</published><updated>2008-11-03T09:58:10.609+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-11-03T09:58:10.609+08:00</app:edited><title>Rule of Representation</title><content type="html">I have been doing some studying on the internet in my free time (not that I have too much of that nowadays) and I stumbled upon the &lt;a href="http://www.faqs.org/docs/artu/ch01s06.html"&gt;Unix Philosophy&lt;/a&gt;. This is a philosophy, not method,  for building programs and systems.&lt;br /&gt;As I went through the rules, I found something interesting. I'll paste it here:&lt;br /&gt;&lt;div class="titlepage"&gt;&lt;div&gt;&lt;h3 class="title"&gt;&lt;a id="id2878263"&gt;&lt;/a&gt;&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;blockquote&gt;&lt;div class="titlepage"&gt;&lt;div&gt;&lt;h3 class="title"&gt;&lt;a id="id2878263"&gt;Rule of Representation: Fold knowledge into data,  so program logic can be stupid and robust.&lt;/a&gt;&lt;/h3&gt;&lt;/div&gt;&lt;/div&gt;&lt;p&gt;&lt;a id="id2878263"&gt;Even the simplest procedural logic is hard for humans to verify, but quite complex data structures are fairly easy to model and reason about. To see this, compare the expressiveness and explanatory power of a diagram of (say) a fifty-node pointer tree with a flowchart of a fifty-line program.  Or, compare an array initializer expressing a conversion table with an equivalent switch statement. The difference in transparency&lt;/a&gt;&lt;a id="id2878281" class="indexterm"&gt; and clarity is dramatic. See Rob Pike's &lt;/a&gt;&lt;a href="http://www.faqs.org/docs/artu/ch01s06.html#rule5"&gt;Rule 5&lt;/a&gt;.&lt;/p&gt;&lt;p&gt;Data is more tractable than program logic. It follows that where you see a choice between complexity in data structures and complexity in code, choose the former. More: in evolving a design, you should actively seek ways to shift complexity from code to data.&lt;/p&gt;&lt;p&gt;&lt;a id="id2878312" class="indexterm"&gt;&lt;br /&gt;&lt;/a&gt;&lt;/p&gt;&lt;/blockquote&gt;&lt;p&gt;&lt;a id="id2878312" class="indexterm"&gt;&lt;/a&gt;&lt;/p&gt;I have read in the past many articles about how data trumps programing algorithms in many cases and I know that Google uses this principle on their searches. Its just nice to see that its been thought about and discussed in the days of when Unix was thought of.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/375697951860081841-4106059775976359754?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/4106059775976359754/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=4106059775976359754" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/4106059775976359754?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/4106059775976359754?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/11/rule-of-representation.html" title="Rule of Representation" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;A0EBQ347fSp7ImA9WxVVFE4.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-7447870664049697193</id><published>2008-10-24T19:21:00.004+08:00</published><updated>2009-03-07T23:27:32.005+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2009-03-07T23:27:32.005+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MySQL Magazine" /><title>MySQL Magazine is Out and</title><content type="html">&lt;a href="http://www.paragon-cs.com/mag/"&gt;MySQL Magazine&lt;/a&gt; is Out and .. I wrote an aticle on it!&lt;br /&gt;&lt;br /&gt;The magazine looks very shiny. Go get your copy.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/375697951860081841-7447870664049697193?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/7447870664049697193/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=7447870664049697193" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/7447870664049697193?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/7447870664049697193?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/10/mysql-magazine-is-out-and.html" title="MySQL Magazine is Out and" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;Dk4MR3k8fCp7ImA9WxRXFk0.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-8193990101398745912</id><published>2008-10-22T00:00:00.001+08:00</published><updated>2008-10-22T00:03:06.774+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-10-22T00:03:06.774+08:00</app:edited><title>New Job, New Responsibilities</title><content type="html">I recently took up a position as an IT and Internet Manager at &lt;span class="blsp-spelling-error" id="SPELLING_ERROR_0"&gt;MobileFun&lt;/span&gt; UK.&lt;br /&gt;The position itself is very interesting. The company is very aggressively trying to grow and has lots of new ideas. At the same time, I am stuck with some legacy systems that I need sort out asap. The people here are really very nice. Birmingham is also really nice and far cheaper then London for house prices.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;My responsibilities include:&lt;br /&gt;&lt;ul&gt;&lt;li&gt;Maintaining the web servers&lt;/li&gt;&lt;li&gt;Leading the web development team&lt;/li&gt;&lt;li&gt;Maintaining all the servers and desktops inside the company - some are quite old.&lt;/li&gt;&lt;li&gt;Leading the internal application development team&lt;/li&gt;&lt;li&gt;The databases and the business intelligence of the company - we use MySQL 4 and 5 (I need to upgrade them)&lt;/li&gt;&lt;li&gt;And.. the phones for the entire company - don't know why.&lt;/li&gt;&lt;/ul&gt;&lt;br /&gt;So I have quite a lot of work to get done and I hope that I will have some interesting stories to blog about in the future. They will probably about fixing legacy systems...&lt;br /&gt;Wish me luck.&lt;div class="blogger-post-footer"&gt;&lt;img width='1' height='1' src='https://blogger.googleusercontent.com/tracker/375697951860081841-8193990101398745912?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/8193990101398745912/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=8193990101398745912" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/8193990101398745912?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/8193990101398745912?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/10/new-job-new-responsibilities.html" title="New Job, New Responsibilities" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry><entry gd:etag="W/&quot;AkMFQX4_eyp7ImA9WxRRF08.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-9120136665579589798</id><published>2008-09-28T09:07:00.008+08:00</published><updated>2008-09-30T06:46:50.043+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-30T06:46:50.043+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="dtdd" /><title>Wikipedia - Decision Table Driven Development</title><content type="html">I have been researching &lt;a href="http://mysqlbarbeque.blogspot.com/2008/02/using-business-rules-in-mysql-overview.html"&gt;Business Rules&lt;/a&gt;, Decision Trees and &lt;a href="http://mysqlbarbeque.blogspot.com/2008/09/decisions-decisions.html"&gt;Decision Tables&lt;/a&gt; and how they can be used in a relational database for some time. I decided to write a Wikipedia article about a new software development methodology I call "&lt;a href="http://en.wikipedia.org/wiki/Decision_Table_Driven_Development"&gt;Decision Table Driven Development&lt;/a&gt;".&lt;div&gt;I believe its a good idea, but then again, I am biased. &lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I am new to wikipedia and recently learned that I need to move my writing style away from "my opinion" to "concrete research". I already got a notice that I have 4-5 days to improve the article or it will get deleted :(&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Its still a work-in-progress, but if you would like to read it, comment on it or ask questions, I would be very happy to reply. If you have written articles in wikipedia in the past and have some suggestions on what I should change, please also give me your feedback.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Edit: The Article was moved to Google Knol -&gt; &lt;a href="http://knol.google.com/k/jonathan-levin/decision-table-driven-development/1t38jrcpcg5ay/3#"&gt;dtdd&lt;/a&gt;&lt;/div&gt;&lt;div&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/375697951860081841-9120136665579589798?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/9120136665579589798/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=9120136665579589798" title="7 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/9120136665579589798?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/9120136665579589798?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/09/wikipedia-decision-table-driven.html" title="Wikipedia - Decision Table Driven Development" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">7</thr:total></entry><entry gd:etag="W/&quot;CU4ESX8-eyp7ImA9WxRSGU4.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-6034327132785752121</id><published>2008-09-20T18:29:00.011+08:00</published><updated>2008-09-21T02:05:08.153+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-21T02:05:08.153+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="MySQL" /><category scheme="http://www.blogger.com/atom/ns#" term="UK" /><category scheme="http://www.blogger.com/atom/ns#" term="MS SQL" /><category scheme="http://www.blogger.com/atom/ns#" term="Oracle" /><category scheme="http://www.blogger.com/atom/ns#" term="Jobs" /><title>The Database Job Situation in England</title><content type="html">Well, I'm back in "Blighty" (that's slang for Britain). I've been trying for the last 2-3 weeks to find jobs in the UK.&lt;div&gt;Since I wrote a while ago &lt;a href="http://mysqlbarbeque.blogspot.com/2008/07/which-database-to-choose-when-looking.html"&gt;"Which Database to Choose When Looking for a Job"&lt;/a&gt;, I wanted to continue it with some of my findings. I did a lot research on IT specific job sites and used 2 main searches, "database developer" (because that's what I want to do) and "mysql" to help me find job posts that I was interested in. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Jobs Situation for "Database Developer"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I'll describe the results for this search in percentages. &lt;/div&gt;&lt;div&gt;Firstly, 90% of the jobs are for MS SQL server. Those jobs usually stick to mainly developing and not administrating. In those 90% you have a good mix of junior positions(22-28k GBP per year), medium paid positions (30-45k GBP per year) and advanced positions (50-70k GBP per year). &lt;/div&gt;&lt;div&gt;The second 5% are for Oracle developers. Almost always it is developing and DBA'ing. The positions are usually medium positions (40-55k GBP per year) to advanced positions (60-90k GBP per year).&lt;/div&gt;&lt;div&gt;The third 4% are for Data Analysts. Usually this would mean 80% chance of MS SQL and the rest would be Oracle or mixed Oracle and MS SQL experience. Data Analysts are usually half ETL developers (because they need to get the data first) and half report builders. You would probably have to have some data warehouse experience. Jobs pay 30-55k GBP accordingly and mainly require you to know SQL, some statistics and a lot of experience.&lt;/div&gt;&lt;div&gt;The last 1% are Data Analysts again, but this time with an emphasis on Excel, VBA, Access and SQL server (a lot of people write MySQL here by mistake and it shows up on my other search :) ). This is more for businesses to analyse data or help other peole analyse data by helping them out with Excel functions. These jobs are mainly for finance sectors and quite a bit of stock trading companies and require a lot of statistics knowledge. Jobs pay 35-70k GBP per year.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Job Situation for "MySQL"&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;So this is 98% PHP and MySQL positions. Its almost always together. Jobs can be for junior positions (18-22k GBP per year), medium positions (25-32k GBP per year) and advanced position (35-55k GBP per year).&lt;/div&gt;&lt;div&gt;The second 2% are Java Developer positions with MySQL inside the wording. Jobs seem to pay 20-30k GBP per year and are usually related to website. By the way, I saw 1-2 Ruby developer job posts on this MySQL search, but that doesn't mean I would get the same if I just did a search for Ruby.&lt;/div&gt;&lt;div&gt;The next 1% is for Linux and Windows Administrators that need to setup MySQL and Oracle as well as maintain the system itself. Some posts are for Linux platforms only but more then half require you to know both Linux and Windows servers. Jobs pay 40-55k GBP per year.&lt;/div&gt;&lt;div&gt;The last 1% is for MySQL Administrators. Jobs are only for advanced positions with 3-5 years experience being a database admin for MySQL. Sometimes its a combination of Oracle and MySQL. Jobs pay 40-55k GBP per year.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Trends I Have Noticed&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Clearly, if you want to develop with databases in the UK, you would make your life easier and focus on MS SQL server. This could mean focusing on&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;T-SQL between databases&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Helping out VB.NET or C# developers&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Doing ETL work with the built in packages MS offers you&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Doing Reports with the built in packages&lt;br /&gt;&lt;/li&gt;&lt;li&gt;Maintaining the database and optimizing it &lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;It seems to me that if you want to get a job working on developing in databases, MS SQL would be a really good place to start. Sectors that usually use MS SQL are finance, banks, insurance, health.. and almost all other companies in the UK apart from Web companies.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Web companies on the other hand (the large ones or digital advertising companies), use a combination of MySQL and Oracle. From the examples I have found, they use MySQL for the actual websites and then get the data (ETL) into Oracle (which they use as a data warehouse) to analyze it and make Excel reports. They said that Oracle is much better at analyzing functions. They do admit that they could "eventually" write the code they in MySQL, but the additional functionality in Oracle saves them time. &lt;/div&gt;&lt;div&gt;&lt;a href="http://mysqlbarbeque.blogspot.com/2008/03/list-of-open-source-alternatives-to.html"&gt;I would argue &lt;/a&gt;that they should just use some ETL/Reporting suite like Pentaho or Jaspersoft. Both produce Excel reports, both are more GUI-y than hand-coding SQL and probably are a better investment for their purpose.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Finally, PHP developers are expected to be "smart enough" to maintain and optimize MySQL databases. In small web companies, this is usually the standard as they may not have enough money to hire someone specifically to maintain the MySQL server(s). This problem can also be found in .NET environments, however, there are much more .NET environments that can afford to hire someone who specializes in databases.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Bibliography&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;The websites I used were:&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;ul&gt;&lt;li&gt;&lt;a href="http://www.cwjobs.co.uk/"&gt;www.cwjobs.co.uk&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.jobsite.co.uk/"&gt;www.jobsite.co.uk&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.jobserve.com/"&gt;www.jobserve.com&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;li&gt;&lt;a href="http://www.cityjobs.co.uk/"&gt;www.cityjobs.co.uk&lt;/a&gt;&lt;br /&gt;&lt;/li&gt;&lt;/ul&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;I hope this post helps other people who are looking for Database jobs in the UK.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Edit: For thos interested, I have found a copy of a test some employer asks its future MS SQL developers to do.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Test&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;1.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;If table X contains 5 rows and table Y contains 7 rows, how many records will be returned by a CROSS JOIN on both tables?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;a.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;5&lt;/div&gt;&lt;div&gt;b.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;7&lt;/div&gt;&lt;div&gt;c.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;12&lt;/div&gt;&lt;div&gt;d.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;35&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;2.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;What is the maximum number of clustered indexes that can be defined on a table?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;a.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;8,032&lt;/div&gt;&lt;div&gt;b.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;1&lt;/div&gt;&lt;div&gt;c.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Unlimited&lt;/div&gt;&lt;div&gt;d.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Depends on the SQL Server edition&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;3.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Which of the following statements is NOT true?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;a.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;A composite index consists of more than one column&lt;/div&gt;&lt;div&gt;b.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;A composite index cannot contain an identity column&lt;/div&gt;&lt;div&gt;c.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;A composite index can also be clustered&lt;/div&gt;&lt;div&gt;d.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;A composite index can also be unique&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;4.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Using the Latin1_General_CI_AS collation, what is the result of the following expression if @Country = ‘USA’?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;ISNULL(NULLIF(@Country, 'usa'), 'United States of America')&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;a.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;USA&lt;/div&gt;&lt;div&gt;b.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;usa&lt;/div&gt;&lt;div&gt;c.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;United States of America&lt;/div&gt;&lt;div&gt;d.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;NULL&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;5.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Which of the following is not a T-SQL function?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;a.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;COALESCE&lt;/div&gt;&lt;div&gt;b.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;CONVERT&lt;/div&gt;&lt;div&gt;c.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;TRIM&lt;/div&gt;&lt;div&gt;d.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;NULLIF&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;6.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;When creating a VIEW, you can only specify an ORDER BY clause if:-&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;a.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;TOP is also specified&lt;/div&gt;&lt;div&gt;b.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;the SCHEMABOUND option is also specified&lt;/div&gt;&lt;div&gt;c.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;the GROUP BY clause is also specified&lt;/div&gt;&lt;div&gt;d.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;all the columns specified in the ORDER BY clause are contained in the SELECT list&lt;/div&gt;&lt;div&gt; &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;7.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;What does the following query do?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SELECT&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;COUNT(so.name)&lt;/div&gt;&lt;div&gt;FROM&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;syscolumns sc&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-tab-span" style="white-space:pre"&gt;  &lt;/span&gt;INNER JOIN sysobjects so ON sc.id = so.id&lt;/div&gt;&lt;div&gt;WHERE&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;sc.name = 'Site' AND xtype = 'U'&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;a.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;It counts the number of COLUMNS in the VIEW named ‘Site’&lt;/div&gt;&lt;div&gt;b.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;It counts the number of VIEWS which contain a COLUMN named ‘Site’&lt;/div&gt;&lt;div&gt;c.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;It counts the number of TABLES named ‘Site’&lt;/div&gt;&lt;div&gt;d.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;It counts the number of TABLES which contain a COLUMN named ‘Site’&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;8.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;How do you produce a carriage return and line feed in SQL Server?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;a.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;CHAR(10) &amp;amp; CHAR(13)&lt;/div&gt;&lt;div&gt;b.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;CHR(10) &amp;amp; CHR(13)&lt;/div&gt;&lt;div&gt;c.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;CHAR(13) + CHAR(10)&lt;/div&gt;&lt;div&gt;d.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;CHR(13) + CHR(10)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;9.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;Which of the following statements would you use to disable a trigger on the Employee table called Employee_ITrig?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;a.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;DISABLE TRIGGER Employee.Employee_ITrig&lt;/div&gt;&lt;div&gt;b.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;ALTER TABLE Employee DISABLE TRIGGER Employee_ITrig&lt;/div&gt;&lt;div&gt;c.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;ALTER TRIGGER Employee_ITrig DISABLE&lt;/div&gt;&lt;div&gt;d.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;ALTER TABLE Employee DELETE TRIGGER Employee_ITrig&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;10.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;What is syntactically wrong with the following statement?&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;UPDATE Person SET Surname = 'O'Reilly' WHERE PersonId = 10&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;a.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;If PersonId is not unique, you may update more than one row&lt;/div&gt;&lt;div&gt;b.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;There statement is missing a fully qualified table name&lt;/div&gt;&lt;div&gt;c.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;There is an unterminated literal string within the statement&lt;/div&gt;&lt;div&gt;d.&lt;span class="Apple-tab-span" style="white-space:pre"&gt; &lt;/span&gt;There is an ambiguous field name within the statement&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&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/375697951860081841-6034327132785752121?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/6034327132785752121/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=6034327132785752121" title="2 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/6034327132785752121?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/6034327132785752121?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/09/dba-job-situation-in-england.html" title="The Database Job Situation in England" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">2</thr:total></entry><entry gd:etag="W/&quot;DkUNR308fyp7ImA9WxRTFEs.&quot;"><id>tag:blogger.com,1999:blog-375697951860081841.post-1750407494121721029</id><published>2008-09-03T16:00:00.000+08:00</published><updated>2008-09-04T01:51:36.377+08:00</updated><app:edited xmlns:app="http://www.w3.org/2007/app">2008-09-04T01:51:36.377+08:00</app:edited><category scheme="http://www.blogger.com/atom/ns#" term="decision tables" /><title>Decisions... Decisions</title><content type="html">In my last blog post, I discussed &lt;a href="http://mysqlbarbeque.blogspot.com/2008/08/storing-conditions.html"&gt;storing conditions in the database&lt;/a&gt;. For a quick reminder, I suggested that you store all the under-lying conditions (the if-then-else statements) from your code in your database. From my example, I used "did the sales person sell more then average for that day" ( sold_more_than_average BOOLEAN) and the answer would be True or False.&lt;br /&gt;&lt;br /&gt;In this post, I would like to discuss connecting those same conditions with a decision table.&lt;div&gt;Before I get started, I would like to take a moment and reminisce about some of the previous posts I talked about decision tables to help explain them better.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mysqlbarbeque.blogspot.com/2007/11/decision-tables-and-your-database.html"&gt;Decision Tables and Your Database&lt;/a&gt; - November 25, 2007&lt;br /&gt;Where I talk about decision trees and decision tables.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mysqlbarbeque.blogspot.com/2008/02/using-business-rules-in-mysql-overview.html"&gt;Using Business Rules in MySQL&lt;/a&gt; - February 20, 2008&lt;br /&gt;I have a very graphical example of how to use decision trees and tables in that post.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mysqlbarbeque.blogspot.com/2008/06/decisions-in-your-tables.html"&gt;Decisions in Your Tables&lt;/a&gt; - June 30, 2008&lt;br /&gt;My most up to date and well thought out explanation for understanding and implementing decision tables.&lt;br /&gt;&lt;br /&gt;&lt;a href="http://mysqlbarbeque.blogspot.com/2008/08/storing-conditions.html"&gt;Storing Conditions&lt;/a&gt; - August 25, 2008&lt;div&gt;&lt;span class="Apple-style-span" style="color: rgb(85, 85, 85); "&gt;&lt;span class="Apple-style-span" style="color: rgb(0, 0, 0);  "&gt;&lt;span class="Apple-style-span"  style="font-size:medium;"&gt;This was the prelude to this post. It explains the reasoning behind simply storing your conditions, while this chapter explains how to make further use of them along side decision tables. &lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;So What is the Trick?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;The trick is basically, you take the conditions you have stored and do a search in the decision table to get only one result back.&lt;/div&gt;&lt;div&gt;Confusing? read on. It will become clearer.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Example&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Now I would like to show how to integrate conditions stored in the database with decision tables. Once again, I will do so with less words and more examples.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Story&lt;/span&gt; - Maintenance and Cleanliness in a Hotel&lt;br /&gt;&lt;br /&gt;An owner of a small guesthouse would like to manage better the cleaning woman and how often she should clean the rooms of the guesthouse. After discussing the issue with her, they decide that she will clean each room, once every 2 days under the condition that there are guests using the room (don't look at me, I was in a guesthouse that the cleaning lady cleaned once every 3 days or whenever she felt like it).&lt;br /&gt;&lt;br /&gt;The owner would also like the cleaning lady to clean rooms before new guests come in and straight after they leave so that people can view a clean room when no one is using it. Also, if there is something wrong with the room (like a broken sink) then there is no point to clean the room until it is fixed.&lt;br /&gt;&lt;br /&gt;The owner would also like to keep track of booked and available rooms in this system.&lt;br /&gt;Using &lt;a href="http://dev.mysql.com/workbench/"&gt;MySQL WorkBench&lt;/a&gt; I designed the database model and it looks like this&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://xs130.xs.to/xs130/08350/table1473.gif"&gt;&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://xs130.xs.to/xs130/08350/table1473.gif"&gt;&lt;img style="cursor: pointer; width: 644px; height: 338px;" src="http://xs130.xs.to/xs130/08350/table1473.gif" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;Bare with me for the explanation. Lets take a look at the rather multi-columned Rooms table:&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://xs130.xs.to/xs130/08350/table2639.gif"&gt;&lt;img style="cursor: pointer; width: 545px; height: 316px;" src="http://xs130.xs.to/xs130/08350/table2639.gif" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;div style="text-align: left;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;As we can see, at the top is the standard data that you would need for the table - room id and the day. I also needed some more input from the user, so I added those 2 extra fields.&lt;br /&gt;The conditions are what I talked about taking the if-then-else statements and putting the results in your database.&lt;br /&gt;Is_room_booked - is the room booked or will have people using the room on that day.&lt;br /&gt;Is_first_day and Is_last_day - are conditions to know if the room needs a special kind of cleaning. First day needs to be prepared for visit and cleaned. On the last day, the room needs to be cleaned for viewing only (which could mean, no towels and toilet paper are left in the room).&lt;br /&gt;has_been_cleaned_yesterday - has to do with the arrangement for the cleaner that she wont have to clean the room everyday. If she did clean yesterday, she doesn't have to today. If she didn't clean yesterday, then she does today.&lt;br /&gt;&lt;br /&gt;The decisions are what you want to do with the data you have. Once you have the conditions, you need to query the decision tables. The decision table holds the combinations of the conditions and decisions. The query will then give you a result of action you should take.&lt;br /&gt;When you have all the combinations pre-defined, you have no side effects. That is to say, if you have if-then statement (that you wrote it quickly), you might have missed a side effect when you didn't use an ELSEIF statement for a certain condition.&lt;br /&gt;&lt;br /&gt;&lt;div style="text-align: center;"&gt;&lt;a onblur="try {parent.deselectBloggerImageGracefully();} catch(e) {}" href="http://xs130.xs.to/xs130/08350/table3910.gif"&gt;&lt;img style="cursor: pointer; width: 675px; height: 221px;" src="http://xs130.xs.to/xs130/08350/table3910.gif" alt="" border="0" /&gt;&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;(Please pretend that 0 is False and 1 is True)&lt;br /&gt;Here we have the decision table with all (or most) of the conditions that might happen and their results. Notice the primary keys at the top of the table to ensure that there wont be 2 conditions twice in the table (another benefit to &lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.20.7871"&gt;use relational database with decision tables&lt;/a&gt;). Please also notice that I could have just joined the conditions to this table, but I decided to keep a copy of the decision in the main table so that if any changes are made, the old results will still remain in the main table.&lt;br /&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;So What was that Trick Again?&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;As I mentioned before, you take the conditions from the table, you use those conditions to do a search in the decision table. So you can do: &lt;/div&gt;&lt;div&gt;&lt;blockquote&gt;SELECT * FROM decision_maintenance WHERE is_booked = True AND....&lt;/blockquote&gt;&lt;/div&gt;&lt;div&gt;You can then insert the results into the rooms table, since you should only get one result. You can even set up a Trigger in the database to do it for you.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Small Note - If you forgot to input a line in the decision table, you can make a function (in any language) that if you do not get a result from the decision table that it should add a new line and send an error to the user to choose a decision for those conditions. &lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;And Now, The Code&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;br /&gt;&lt;/span&gt;If you don't need to see this part, skip ahead.&lt;/div&gt;&lt;div&gt;(Code from MySQL WorkBench - p.s. I had an error on a constraint with this program. I had to remove it manually)&lt;br /&gt;&lt;span style="font-style: italic;"&gt;&lt;/span&gt;&lt;blockquote&gt;&lt;span style="font-style: italic;"&gt;-- -----------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- Table `mydb`.`customers`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- -----------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;DROP TABLE IF EXISTS `mydb`.`customers` ;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;CREATE  TABLE IF NOT EXISTS `mydb`.`customers` (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `idcustomers` INT NOT NULL AUTO_INCREMENT ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `customer_name` VARCHAR(45) NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  PRIMARY KEY (`idcustomers`) )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;ENGINE = InnoDB;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- -----------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- Table `mydb`.`rooms_info`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- -----------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;DROP TABLE IF EXISTS `mydb`.`rooms_info` ;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;CREATE  TABLE IF NOT EXISTS `mydb`.`rooms_info` (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `idrooms` TINYINT UNSIGNED NOT NULL AUTO_INCREMENT ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `room_name` VARCHAR(45) NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  PRIMARY KEY (`idrooms`) )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;ENGINE = InnoDB;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- -----------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- Table `mydb`.`rooms`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- -----------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;DROP TABLE IF EXISTS `mydb`.`rooms` ;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;CREATE  TABLE IF NOT EXISTS `mydb`.`rooms` (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `idrooms` TINYINT UNSIGNED NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `date` DATE NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `idcustomers` INT UNSIGNED,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `has_been_cleaned` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `has_some_problem` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `is_booked` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `is_first_day` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `is_last_day` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `has_been_cleaned_yesterday` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `need_cleaning` BOOLEAN NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `prepare_for_visit` BOOLEAN NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `available` BOOLEAN NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  PRIMARY KEY (`idrooms`, `date`) ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  INDEX fk_customers (`idcustomers` ASC) ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  INDEX fk_rooms (`idrooms` ASC) ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  CONSTRAINT `fk_rooms`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    FOREIGN KEY (`idrooms` )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    REFERENCES `mydb`.`rooms_info` (`idrooms` )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    ON DELETE NO ACTION&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;    ON UPDATE NO ACTION)&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;ENGINE = InnoDB;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- -----------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- Table `mydb`.`decision_available`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- -----------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;DROP TABLE IF EXISTS `mydb`.`decision_available` ;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;CREATE  TABLE IF NOT EXISTS `mydb`.`decision_available` (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `is_booked` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `has_some_problem` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `available` BOOLEAN NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  PRIMARY KEY (`is_booked`, `has_some_problem`) )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;ENGINE = MyISAM;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- -----------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- Table `mydb`.`decision_maintenance`&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;-- -----------------------------------------------------&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;DROP TABLE IF EXISTS `mydb`.`decision_maintenance` ;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;CREATE  TABLE IF NOT EXISTS `mydb`.`decision_maintenance` (&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `has_been_cleaned_yesterday` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `has_some_problem` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `is_booked` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `is_first_day` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `is_last_day` BOOLEAN NOT NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `needs_cleaning` BOOLEAN NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `prepare_for_visit` BOOLEAN NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  `prepare_for_view` BOOLEAN NULL ,&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;  PRIMARY KEY (`has_been_cleaned_yesterday`, `is_booked`, `is_first_day`, `is_last_day`, `has_some_problem`) )&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;ENGINE = MyISAM;&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (False,False,False,False,False,False,False,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (False,False,False,False,True,False,False,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (False,False,False,True,False,True,False,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (True,False,False,False,False,False,False,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (False,True,False,True,False,True,True,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (True,True,False,True,False,True,True,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (False,False,True,True,False,True,False,True);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (True,False,True,True,False,True,False,True);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (True,False,False,False,True,False,False,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (True,True,False,True,True,False,False,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (True,False,True,True,True,False,False,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (False,False,False,True,True,False,False,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_maintenance` VALUES (False,True,False,True,True,False,False,False);&lt;/span&gt;&lt;br /&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_available` VALUES (True,False,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_available` VALUES (False,True,False);&lt;/span&gt;&lt;br /&gt;&lt;span style="font-style: italic;"&gt;INSERT INTO `mydb`.`decision_available` VALUES (False,False,True);&lt;/span&gt;&lt;/blockquote&gt;&lt;br /&gt;&lt;span style="font-weight: bold;"&gt;Conclusion - Some Pro's and Con's&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;&lt;span class="Apple-style-span" style="font-weight: normal;"&gt;1) Saves CPU usage by using more hard disk space&lt;/span&gt;&lt;br /&gt;&lt;/span&gt;Pro: Saves hard disk usage and CPU usage from repeated processing. &lt;br /&gt;Con: Uses more space on the hard disk and uses the CPU (probably when you insert data) to processes it one time &lt;/div&gt;&lt;div&gt;2)  Helps with data analysis&lt;/div&gt;&lt;div&gt;Pro: Simplifies OLAP and BI operations&lt;/div&gt;&lt;div&gt;3) Leaves clues about how the data was processed. &lt;/div&gt;&lt;div&gt;Pro: Helps a lot with debugging and possibly documentation.&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Con: Keeps extra data that might not be needed for later. &lt;/div&gt;&lt;div&gt;4) Helps with the design of the database as well as with the code. &lt;/div&gt;&lt;div&gt;Pro: While planning the database design for the example, I ran into many situations where I re-did some of the design during the actual design process. This was because I had to think ahead for which conditions I might need for the decisions. I found this far more helpful then designing the database first, then finding out during the coding phase, that I need to make changes to the database.&lt;/div&gt;&lt;div&gt;5) Helps manage decisions&lt;/div&gt;&lt;div&gt;Pro: Allows you to "configure" your decisions by making simple changes to the table. As apposed to looking through your code to make the changes.&lt;/div&gt;&lt;div&gt;6) Leverages regular database search functionality to use your decisions&lt;/div&gt;&lt;div&gt;Pro: You can use regular SELECT statements to find out which decision to take.&lt;/div&gt;&lt;div&gt;Con: Even though you can quickly find which decision to take, you cannot take the action needed. The database will just give you the data and you might have to set up CASE or IF statements in your code to know what to do with the decisions.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Some more points which are arguable..&lt;/div&gt;&lt;div&gt;7) Is database and programing language agnostic.&lt;/div&gt;&lt;div&gt;You are not locked in to database vendors or "slow" programming languages, because you can relatively easily change either database or programing language. The database just keeps the data, the programming language is restricted to very defined data it needs to provide to it and the actual decisions/rules are mostly kept in the database but as data.&lt;/div&gt;&lt;div&gt;8) Scales&lt;/div&gt;&lt;div&gt;Using single table is faster then using JOINs. If you have a table with everything you need inside of it, then in theory, you could scale better.  As well as the fact that you might not need to process data again and again. I understood that facebook uses very very few joins in their code and that everything is in single tables (they might duplicate the data to keep it that way).&lt;/div&gt;&lt;div&gt;9) Keeps the data cleaner&lt;/div&gt;&lt;div&gt;Only if you setup conditions for that to happen, but could still help analyze the data for integrity.&lt;/div&gt;&lt;div&gt;10) Develop software faster&lt;/div&gt;&lt;div&gt;In connection to point 4, but a shameless statement that would need much more proof to back it up.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;span class="Apple-style-span" style="font-weight: bold;"&gt;Bibliography&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;Decision tables have been studied in academia since the 80s. Here are some papers on the subject touching on different fields, from data mining to artificial intelligence:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.20.7871"&gt;Decision tables: Scalable classification exploring RDBMS capabilities&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;div&gt;&lt;a href="http://www.springerlink.com/content/p5n736u105315054/"&gt;The power of decision tables&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://www.springerlink.com/content/x3mq6620q0864445/"&gt;Relational Data Mining&lt;/a&gt;&lt;/div&gt;&lt;div&gt;&lt;a href="http://mansci.highwire.org/cgi/content/abstract/49/3/312"&gt;Using Neural Network Rule Extraction and Decision Tables for Credit–Risk Evaluation&lt;/a&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;If you have any feedback about my idea, I would be glad to hear it.&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&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/375697951860081841-1750407494121721029?l=mysqlbarbeque.blogspot.com'/&gt;&lt;/div&gt;</content><link rel="replies" type="application/atom+xml" href="http://mysqlbarbeque.blogspot.com/feeds/1750407494121721029/comments/default" title="Post Comments" /><link rel="replies" type="text/html" href="https://www.blogger.com/comment.g?blogID=375697951860081841&amp;postID=1750407494121721029" title="0 Comments" /><link rel="edit" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1750407494121721029?v=2" /><link rel="self" type="application/atom+xml" href="http://www.blogger.com/feeds/375697951860081841/posts/default/1750407494121721029?v=2" /><link rel="alternate" type="text/html" href="http://mysqlbarbeque.blogspot.com/2008/09/decisions-decisions.html" title="Decisions... Decisions" /><author><name>Jonathan</name><uri>http://www.blogger.com/profile/17336586681878234499</uri><email>BoogyBo@gmail.com</email><gd:extendedProperty name="OpenSocialUserId" value="06703318287193483852" /></author><thr:total xmlns:thr="http://purl.org/syndication/thread/1.0">0</thr:total></entry></feed>
