{"id":108,"date":"2011-05-23T01:41:24","date_gmt":"2011-05-22T23:41:24","guid":{"rendered":"http:\/\/demianlabs.com\/lab\/?p=108"},"modified":"2013-08-25T12:46:54","modified_gmt":"2013-08-25T10:46:54","slug":"how-to-skyrocket-mysql-performance-the-easy-way","status":"publish","type":"post","link":"https:\/\/demianlabs.com\/lab\/post\/how-to-skyrocket-mysql-performance-the-easy-way\/","title":{"rendered":"How to skyrocket MySQL performance the easy way"},"content":{"rendered":"<p>When you see your average page loading time going from 0.08 sec to 1.40 sec you know it&#8217;s time to do someting about it. I&#8217;ve run into this situation a few days ago and made some tweaks to my database. Now the average loading time is even lower at 0.05 sec. Here is how to do it.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-118\" title=\"MySQL logo\" alt=\"MySQL logo\" src=\"https:\/\/demianlabs.com\/lab\/wp-content\/uploads\/Logo-mysql.jpg\" width=\"399\" height=\"291\" srcset=\"https:\/\/demianlabs.com\/lab\/wp-content\/uploads\/Logo-mysql.jpg 399w, https:\/\/demianlabs.com\/lab\/wp-content\/uploads\/Logo-mysql-300x218.jpg 300w\" sizes=\"auto, (max-width: 399px) 100vw, 399px\" \/><\/p>\n<h4>1. Create indexes<\/h4>\n<p>Indexes are a way for mySQL to scan through tables very fast. The greater the number of rows, the greater the speed improvement. The mySQL manual claims that in a table with 1000 rows, an index could speed up data retrieval by 100 times.<\/p>\n<p>Let&#8217;s see how it works in action. Let&#8217;s assume for example that we have a simple application that stores all books in a public library. We will need a books table and an authors table to store our data. Since an author may have written many books, and some books can have multiple authors (like many tech books) this is a many to many relationship. So we also need a books_authors table for relating books to authors. So our tables will be:<\/p>\n<p>1. books<\/p>\n<pre>CREATE TABLE books (\r\n  ID INT,\r\n  title VARCHAR(255),\r\n  ISBN VARCHAR(255),\r\n  date_published (date)\r\n)<\/pre>\n<p>2. books_authors<\/p>\n<pre>CREATE TABLE books_authors (\r\n  ID INT,\r\n  book_id INT,\r\n  author_id INT\r\n)<\/pre>\n<p>3. authors<\/p>\n<pre>CREATE TABLE authors (\r\n  ID INT,\r\n  name VARCHAR(255),\r\n)<\/pre>\n<p>Primary keys are automatically indexed by mySQL so we will turn our attention to the books_authors table. The reason is that there will be a lot of work done by mySQL in that table, since it acts as the glue for the other two. Depending on the type of your select queries you may want to index other columns as well, such as the ISBN column if you want to search for books by their ISBN. However if you make the ISBN unique it will be also automatically indexed by mySQL. This is a great idea since ISBNs are unique anyway.<\/p>\n<p>However, back to our example. Let&#8217;s see the code that will create the indexes.<\/p>\n<pre>CREATE INDEX <em>book_id_index <\/em>ON <em>books_authors <\/em>(<em>book_id<\/em>);\r\nCREATE INDEX <em>author_id <\/em>ON <em>books_authors <\/em>(<em>author_id<\/em>);<\/pre>\n<p>As you may have guessed, the syntax goes like this.<\/p>\n<pre>CREATE INDEX <em>index_name<\/em> ON <em>table<\/em> (<em>column<\/em>);<\/pre>\n<p>&nbsp;<\/p>\n<h4>2. Query cache<\/h4>\n<p>MySQL has the feature of caching select queries along with their results. To make things even better, MySQL serves the same cached results to different clients. A great advantage over classic server side HTML caching. Although query cache is on by default you have to configure the cache size in order for it to work.<\/p>\n<p>To check out the size of the query cache connect to MySQL and issue the following command:<\/p>\n<pre>SHOW VARIABLES LIKE 'query_cache_size';<\/pre>\n<p>The size of query cache should depend on your server&#8217;s RAM. A nice practice is setting it to about half the memory size to allow resources for other services.<\/p>\n<p>To set query cache size to 1MB just do:<\/p>\n<pre>SET GLOBAL query_cache_size = 1000000;<\/pre>\n<p>The first time a select query is executed it will run at normal speed. However consecutive queries will be returned almost instantly since they will be cached. This will speed up even the most simple applications since routine queries, like &#8220;select the 10 latest posts&#8221; will practically always be cached.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Conclusion<\/strong>:<\/p>\n<p>These two simple tips can have an enormous impact on your web application&#8217;s performance. However you should be aware that database optimization is a huge topic and it&#8217;s worth digging deeper into it. Your next stop from here should be <a title=\"Database normalization\" href=\"http:\/\/en.wikipedia.org\/wiki\/Database_normalization\">database normalization<\/a>.<\/p>\n<p>&nbsp;<\/p>\n<p><strong>Reference<\/strong>:<\/p>\n<p>How MySQL Uses Indexes<br \/>\n<a title=\"How MySQL Uses Indexes\" href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.0\/en\/mysql-indexes.html\">http:\/\/dev.mysql.com\/doc\/refman\/5.0\/en\/mysql-indexes.html<\/a><\/p>\n<p>When To Use Indexes In MySQL<br \/>\n<a title=\"When To Use Indexes In MySQL\" href=\"http:\/\/www.howtoforge.com\/when-to-use-indexes-in-mysql-databases\">http:\/\/www.howtoforge.com\/when-to-use-indexes-in-mysql-databases<\/a><\/p>\n<p>Query Cache Configuration<br \/>\n<a title=\"Query Cache Configuration\" href=\"http:\/\/dev.mysql.com\/doc\/refman\/5.1\/en\/query-cache-configuration.html\">http:\/\/dev.mysql.com\/doc\/refman\/5.1\/en\/query-cache-configuration.html<\/a><\/p>\n<p>If you got comments\/suggestions or want updates on new posts be sure to <a href=\"https:\/\/twitter.com\/#!\/VangelisB\">follow me on twitter<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>When you see your average page loading time going from 0.08 sec to 1.40 sec you know it&#8217;s time to do someting about it. I&#8217;ve run into this situation a few days ago and made some tweaks to my database. Now the average loading time is even lower at 0.05 sec. Here is how to [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[11],"tags":[],"class_list":["post-108","post","type-post","status-publish","format-standard","hentry","category-academy"],"_links":{"self":[{"href":"https:\/\/demianlabs.com\/lab\/wp-json\/wp\/v2\/posts\/108","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/demianlabs.com\/lab\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/demianlabs.com\/lab\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/demianlabs.com\/lab\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/demianlabs.com\/lab\/wp-json\/wp\/v2\/comments?post=108"}],"version-history":[{"count":18,"href":"https:\/\/demianlabs.com\/lab\/wp-json\/wp\/v2\/posts\/108\/revisions"}],"predecessor-version":[{"id":126,"href":"https:\/\/demianlabs.com\/lab\/wp-json\/wp\/v2\/posts\/108\/revisions\/126"}],"wp:attachment":[{"href":"https:\/\/demianlabs.com\/lab\/wp-json\/wp\/v2\/media?parent=108"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/demianlabs.com\/lab\/wp-json\/wp\/v2\/categories?post=108"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/demianlabs.com\/lab\/wp-json\/wp\/v2\/tags?post=108"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}