{"id":534,"date":"2008-03-14T21:12:07","date_gmt":"2008-03-15T05:12:07","guid":{"rendered":"http:\/\/multimedia.cx\/eggs\/fast-db-lesson\/"},"modified":"2020-07-25T23:09:04","modified_gmt":"2020-07-26T06:09:04","slug":"fast-db-lesson","status":"publish","type":"post","link":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/","title":{"rendered":"An Object Lesson In Database Optimization"},"content":{"rendered":"<p>I have a tendency to regard a database engine as a black box. I just formulate my queries and count on the engine to make them fast, somehow. I think this is similar to the faith that people tend to place in language compilers&#8211; just write the C code and the compiler will just magically optimize it. And if the code isn&#8217;t fast enough, maybe you should use a higher optimization level. Of course, a computer scientist ought to be able to analyze algorithmic running efficiency and spot opportunities for theoretical improvement, rather than relying on the compiler to insert a faster machine instruction here or there.<\/p>\n<p>I started reading up on MySQL optimization strategies. There are a few things to understand about how the database works under the covers, things that are quite intuitive to anyone who has a semester of data structures and algorithms coursework. The <a href=\"http:\/\/fate.multimedia.cx\/\">FATE database<\/a> is getting slower as it grows larger. The table growing the fastest is test_result. Each build currently generates 111 new rows, one for each active test specification.<\/p>\n<pre>\r\nmysql> SELECT COUNT(test_spec) \r\n       FROM test_result \r\n       WHERE build_record=6742;\r\n+------------------+\r\n| COUNT(test_spec) |\r\n+------------------+\r\n|              111 |\r\n+------------------+\r\n1 row in set (4.12 sec)\r\n<\/pre>\n<p><!--more--><br \/>\n3-4 seconds is nominal currently but will obviously grow. MySQL (perhaps other databases as well) has an EXPLAIN keyword that can be prepended to a SELECT statement to detail fascinating statistics about the query:<\/p>\n<pre>\r\nmysql> EXPLAIN SELECT * \r\n       FROM test_result \r\n       WHERE build_record=6742;\r\n+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+\r\n| id | select_type | table       | type | possible_keys | key  | key_len | ref  | rows   | Extra       |\r\n+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+\r\n|  1 | SIMPLE      | test_result | ALL  | NULL          | NULL | NULL    | NULL | 443099 | Using where |\r\n+----+-------------+-------------+------+---------------+------+---------+------+--------+-------------+\r\n<\/pre>\n<p>From what I read about the foregoing data, a type of &#8220;ALL&#8221; is as bad as it gets. Apparently, it means that all rows were examined. Sure enough&#8211; all 443k rows had to be studied to come up with the query result. This makes sense from an algorithmic perspective&#8211; cover each row in a linear manner. How could this be improved using a rudimentary knowledge of algorithms and data structures? Since the query operates by studying rows based on build_record, how about making an ordered index of build_record numbers that point to their rows and perhaps doing a binary search on the index when build_record is part of the WHERE clause? In fact, MySQL has the same idea. I&#8217;m not sure of the exact technical underpinnings of the indexing mechanism, but this is how you ask MySQL to build and maintain an index:<\/p>\n<pre>\r\nmysql> CREATE INDEX build_record_index \r\n       ON test_result (build_record);\r\n<\/pre>\n<p>What kind of improvement? Check out the explanation (using a different build record to avoid query caching):<\/p>\n<pre>\r\nmysql> EXPLAIN SELECT * \r\n       FROM test_result \r\n       WHERE build_record=6745;\r\n+----+-------------+-------------+------+--------------------+--------------------+---------+-------+------+-------+\r\n| id | select_type | table       | type | possible_keys      | key                | key_len | ref   | rows | Extra |\r\n+----+-------------+-------------+------+--------------------+--------------------+---------+-------+------+-------+\r\n|  1 | SIMPLE      | test_result | ref  | build_record_index | build_record_index | 4       | const |  109 |       |\r\n+----+-------------+-------------+------+--------------------+--------------------+---------+-------+------+-------+\r\n<\/pre>\n<p>Nice. Only 109 rows were inspected, which is kind of strange, since there are 111 rows in the query:<\/p>\n<pre>\r\nmysql> SELECT COUNT(test_spec) \r\n       FROM test_result \r\n       WHERE build_record=6745;\r\n+------------------+\r\n| COUNT(test_spec) |\r\n+------------------+\r\n|              111 |\r\n+------------------+\r\n1 row in set (0.50 sec)\r\n<\/pre>\n<p>And the average query shapes up to be well under a second.<\/p>\n<p>Anyway, I found it all terribly interesting. Further, certain aspects of FATE will be much faster now and will scale much better as the data set grows. Maybe someone else will find this article through Google and find this more practical example to be more helpful than the common employee salary database examples that litter the web.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I have a tendency to regard a database engine as a black box. I just formulate my queries and count on the engine to make them fast, somehow. I think this is similar to the faith that people tend to place in language compilers&#8211; just write the C code and the compiler will just magically [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[101],"tags":[],"class_list":["post-534","post","type-post","status-publish","format-standard","hentry","category-fate-server"],"aioseo_notices":[],"aioseo_head":"\n\t\t<!-- All in One SEO 4.9.10 - aioseo.com -->\n\t<meta name=\"description\" content=\"I have a tendency to regard a database engine as a black box. I just formulate my queries and count on the engine to make them fast, somehow. I think this is similar to the faith that people tend to place in language compilers-- just write the C code and the compiler will just magically\" \/>\n\t<meta name=\"robots\" content=\"max-image-preview:large\" \/>\n\t<meta name=\"author\" content=\"Multimedia Mike\"\/>\n\t<link rel=\"canonical\" href=\"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/\" \/>\n\t<meta name=\"generator\" content=\"All in One SEO (AIOSEO) 4.9.10\" \/>\n\t\t<meta property=\"og:locale\" content=\"en_US\" \/>\n\t\t<meta property=\"og:site_name\" content=\"Breaking Eggs And Making Omelettes | Topics On Multimedia Technology and Reverse Engineering\" \/>\n\t\t<meta property=\"og:type\" content=\"article\" \/>\n\t\t<meta property=\"og:title\" content=\"An Object Lesson In Database Optimization | Breaking Eggs And Making Omelettes\" \/>\n\t\t<meta property=\"og:description\" content=\"I have a tendency to regard a database engine as a black box. I just formulate my queries and count on the engine to make them fast, somehow. I think this is similar to the faith that people tend to place in language compilers-- just write the C code and the compiler will just magically\" \/>\n\t\t<meta property=\"og:url\" content=\"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/\" \/>\n\t\t<meta property=\"article:published_time\" content=\"2008-03-15T05:12:07+00:00\" \/>\n\t\t<meta property=\"article:modified_time\" content=\"2020-07-26T06:09:04+00:00\" \/>\n\t\t<meta name=\"twitter:card\" content=\"summary\" \/>\n\t\t<meta name=\"twitter:title\" content=\"An Object Lesson In Database Optimization | Breaking Eggs And Making Omelettes\" \/>\n\t\t<meta name=\"twitter:description\" content=\"I have a tendency to regard a database engine as a black box. I just formulate my queries and count on the engine to make them fast, somehow. I think this is similar to the faith that people tend to place in language compilers-- just write the C code and the compiler will just magically\" \/>\n\t\t<script type=\"application\/ld+json\" class=\"aioseo-schema\">\n\t\t\t{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/fast-db-lesson\\\/#article\",\"name\":\"An Object Lesson In Database Optimization | Breaking Eggs And Making Omelettes\",\"headline\":\"An Object Lesson In Database Optimization\",\"author\":{\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/author\\\/multimedia-mike\\\/#author\"},\"publisher\":{\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/#organization\"},\"datePublished\":\"2008-03-14T21:12:07-07:00\",\"dateModified\":\"2020-07-25T23:09:04-07:00\",\"inLanguage\":\"en-US\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/fast-db-lesson\\\/#webpage\"},\"isPartOf\":{\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/fast-db-lesson\\\/#webpage\"},\"articleSection\":\"FATE Server\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/fast-db-lesson\\\/#breadcrumblist\",\"itemListElement\":[{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs#listItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/multimedia.cx\\\/eggs\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/category\\\/fate-server\\\/#listItem\",\"name\":\"FATE Server\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/category\\\/fate-server\\\/#listItem\",\"position\":2,\"name\":\"FATE Server\",\"item\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/category\\\/fate-server\\\/\",\"nextItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/fast-db-lesson\\\/#listItem\",\"name\":\"An Object Lesson In Database Optimization\"},\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs#listItem\",\"name\":\"Home\"}},{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/fast-db-lesson\\\/#listItem\",\"position\":3,\"name\":\"An Object Lesson In Database Optimization\",\"previousItem\":{\"@type\":\"ListItem\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/category\\\/fate-server\\\/#listItem\",\"name\":\"FATE Server\"}}]},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/#organization\",\"name\":\"Breaking Eggs And Making Omelettes\",\"description\":\"Topics On Multimedia Technology and Reverse Engineering\",\"url\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/author\\\/multimedia-mike\\\/#author\",\"url\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/author\\\/multimedia-mike\\\/\",\"name\":\"Multimedia Mike\",\"image\":{\"@type\":\"ImageObject\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/fast-db-lesson\\\/#authorImage\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/2eb93f7cada658f7986b5092062849fa255779eada3342c8f6b9a40764b95fdd?s=96&d=identicon&r=g\",\"width\":96,\"height\":96,\"caption\":\"Multimedia Mike\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/fast-db-lesson\\\/#webpage\",\"url\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/fast-db-lesson\\\/\",\"name\":\"An Object Lesson In Database Optimization | Breaking Eggs And Making Omelettes\",\"description\":\"I have a tendency to regard a database engine as a black box. I just formulate my queries and count on the engine to make them fast, somehow. I think this is similar to the faith that people tend to place in language compilers-- just write the C code and the compiler will just magically\",\"inLanguage\":\"en-US\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/#website\"},\"breadcrumb\":{\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/fast-db-lesson\\\/#breadcrumblist\"},\"author\":{\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/author\\\/multimedia-mike\\\/#author\"},\"creator\":{\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/author\\\/multimedia-mike\\\/#author\"},\"datePublished\":\"2008-03-14T21:12:07-07:00\",\"dateModified\":\"2020-07-25T23:09:04-07:00\"},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/#website\",\"url\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/\",\"name\":\"Breaking Eggs And Making Omelettes\",\"description\":\"Topics On Multimedia Technology and Reverse Engineering\",\"inLanguage\":\"en-US\",\"publisher\":{\"@id\":\"https:\\\/\\\/multimedia.cx\\\/eggs\\\/#organization\"}}]}\n\t\t<\/script>\n\t\t<!-- All in One SEO -->\n\n","aioseo_head_json":{"title":"An Object Lesson In Database Optimization | Breaking Eggs And Making Omelettes","description":"I have a tendency to regard a database engine as a black box. I just formulate my queries and count on the engine to make them fast, somehow. I think this is similar to the faith that people tend to place in language compilers-- just write the C code and the compiler will just magically","canonical_url":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/","robots":"max-image-preview:large","keywords":"","webmasterTools":{"miscellaneous":""},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/#article","name":"An Object Lesson In Database Optimization | Breaking Eggs And Making Omelettes","headline":"An Object Lesson In Database Optimization","author":{"@id":"https:\/\/multimedia.cx\/eggs\/author\/multimedia-mike\/#author"},"publisher":{"@id":"https:\/\/multimedia.cx\/eggs\/#organization"},"datePublished":"2008-03-14T21:12:07-07:00","dateModified":"2020-07-25T23:09:04-07:00","inLanguage":"en-US","mainEntityOfPage":{"@id":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/#webpage"},"isPartOf":{"@id":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/#webpage"},"articleSection":"FATE Server"},{"@type":"BreadcrumbList","@id":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/#breadcrumblist","itemListElement":[{"@type":"ListItem","@id":"https:\/\/multimedia.cx\/eggs#listItem","position":1,"name":"Home","item":"https:\/\/multimedia.cx\/eggs","nextItem":{"@type":"ListItem","@id":"https:\/\/multimedia.cx\/eggs\/category\/fate-server\/#listItem","name":"FATE Server"}},{"@type":"ListItem","@id":"https:\/\/multimedia.cx\/eggs\/category\/fate-server\/#listItem","position":2,"name":"FATE Server","item":"https:\/\/multimedia.cx\/eggs\/category\/fate-server\/","nextItem":{"@type":"ListItem","@id":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/#listItem","name":"An Object Lesson In Database Optimization"},"previousItem":{"@type":"ListItem","@id":"https:\/\/multimedia.cx\/eggs#listItem","name":"Home"}},{"@type":"ListItem","@id":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/#listItem","position":3,"name":"An Object Lesson In Database Optimization","previousItem":{"@type":"ListItem","@id":"https:\/\/multimedia.cx\/eggs\/category\/fate-server\/#listItem","name":"FATE Server"}}]},{"@type":"Organization","@id":"https:\/\/multimedia.cx\/eggs\/#organization","name":"Breaking Eggs And Making Omelettes","description":"Topics On Multimedia Technology and Reverse Engineering","url":"https:\/\/multimedia.cx\/eggs\/"},{"@type":"Person","@id":"https:\/\/multimedia.cx\/eggs\/author\/multimedia-mike\/#author","url":"https:\/\/multimedia.cx\/eggs\/author\/multimedia-mike\/","name":"Multimedia Mike","image":{"@type":"ImageObject","@id":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/#authorImage","url":"https:\/\/secure.gravatar.com\/avatar\/2eb93f7cada658f7986b5092062849fa255779eada3342c8f6b9a40764b95fdd?s=96&d=identicon&r=g","width":96,"height":96,"caption":"Multimedia Mike"}},{"@type":"WebPage","@id":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/#webpage","url":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/","name":"An Object Lesson In Database Optimization | Breaking Eggs And Making Omelettes","description":"I have a tendency to regard a database engine as a black box. I just formulate my queries and count on the engine to make them fast, somehow. I think this is similar to the faith that people tend to place in language compilers-- just write the C code and the compiler will just magically","inLanguage":"en-US","isPartOf":{"@id":"https:\/\/multimedia.cx\/eggs\/#website"},"breadcrumb":{"@id":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/#breadcrumblist"},"author":{"@id":"https:\/\/multimedia.cx\/eggs\/author\/multimedia-mike\/#author"},"creator":{"@id":"https:\/\/multimedia.cx\/eggs\/author\/multimedia-mike\/#author"},"datePublished":"2008-03-14T21:12:07-07:00","dateModified":"2020-07-25T23:09:04-07:00"},{"@type":"WebSite","@id":"https:\/\/multimedia.cx\/eggs\/#website","url":"https:\/\/multimedia.cx\/eggs\/","name":"Breaking Eggs And Making Omelettes","description":"Topics On Multimedia Technology and Reverse Engineering","inLanguage":"en-US","publisher":{"@id":"https:\/\/multimedia.cx\/eggs\/#organization"}}]},"og:locale":"en_US","og:site_name":"Breaking Eggs And Making Omelettes | Topics On Multimedia Technology and Reverse Engineering","og:type":"article","og:title":"An Object Lesson In Database Optimization | Breaking Eggs And Making Omelettes","og:description":"I have a tendency to regard a database engine as a black box. I just formulate my queries and count on the engine to make them fast, somehow. I think this is similar to the faith that people tend to place in language compilers-- just write the C code and the compiler will just magically","og:url":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/","article:published_time":"2008-03-15T05:12:07+00:00","article:modified_time":"2020-07-26T06:09:04+00:00","twitter:card":"summary","twitter:title":"An Object Lesson In Database Optimization | Breaking Eggs And Making Omelettes","twitter:description":"I have a tendency to regard a database engine as a black box. I just formulate my queries and count on the engine to make them fast, somehow. I think this is similar to the faith that people tend to place in language compilers-- just write the C code and the compiler will just magically"},"aioseo_meta_data":{"post_id":"534","title":null,"description":null,"keywords":null,"keyphrases":null,"primary_term":null,"canonical_url":null,"og_title":null,"og_description":null,"og_object_type":"default","og_image_type":"default","og_image_url":null,"og_image_width":null,"og_image_height":null,"og_image_custom_url":null,"og_image_custom_fields":null,"og_video":null,"og_custom_url":null,"og_article_section":null,"og_article_tags":null,"twitter_use_og":false,"twitter_card":"default","twitter_image_type":"default","twitter_image_url":null,"twitter_image_custom_url":null,"twitter_image_custom_fields":null,"twitter_title":null,"twitter_description":null,"schema":{"blockGraphs":[],"customGraphs":[],"default":{"data":{"Article":[],"Course":[],"Dataset":[],"FAQPage":[],"Movie":[],"Person":[],"Product":[],"ProductReview":[],"Car":[],"Recipe":[],"Service":[],"SoftwareApplication":[],"WebPage":[]},"graphName":"","isEnabled":true},"graphs":[]},"schema_type":null,"schema_type_options":null,"pillar_content":false,"robots_default":true,"robots_noindex":false,"robots_noarchive":false,"robots_nosnippet":false,"robots_nofollow":false,"robots_noimageindex":false,"robots_noodp":false,"robots_notranslate":false,"robots_max_snippet":null,"robots_max_videopreview":null,"robots_max_imagepreview":"large","priority":null,"frequency":null,"location":null,"local_seo":null,"breadcrumb_settings":null,"limit_modified_date":false,"ai":null,"created":"2020-12-31 21:59:33","updated":"2025-12-31 18:50:24","seo_analyzer_scan_date":null},"aioseo_breadcrumb":"<div class=\"aioseo-breadcrumbs\"><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/multimedia.cx\/eggs\" title=\"Home\">Home<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\t<a href=\"https:\/\/multimedia.cx\/eggs\/category\/fate-server\/\" title=\"FATE Server\">FATE Server<\/a>\n\t\t<\/span><span class=\"aioseo-breadcrumb-separator\">&raquo;<\/span><span class=\"aioseo-breadcrumb\">\n\t\t\tAn Object Lesson In Database Optimization\n\t\t<\/span><\/div>","aioseo_breadcrumb_json":[{"label":"Home","link":"https:\/\/multimedia.cx\/eggs"},{"label":"FATE Server","link":"https:\/\/multimedia.cx\/eggs\/category\/fate-server\/"},{"label":"An Object Lesson In Database Optimization","link":"https:\/\/multimedia.cx\/eggs\/fast-db-lesson\/"}],"_links":{"self":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/534","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/comments?post=534"}],"version-history":[{"count":2,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/534\/revisions"}],"predecessor-version":[{"id":4612,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/posts\/534\/revisions\/4612"}],"wp:attachment":[{"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/media?parent=534"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/categories?post=534"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/multimedia.cx\/eggs\/wp-json\/wp\/v2\/tags?post=534"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}