From 9475bbb73886ad358bc4f856a151dd99b63b6b90 Mon Sep 17 00:00:00 2001 From: Akhil Date: Fri, 2 Oct 2020 17:50:59 +0530 Subject: [PATCH 01/14] Added mysql indexing best practices --- SQL/mysql_indexing_best_practices.md | 173 +++++++++++++++++++++++++++ 1 file changed, 173 insertions(+) create mode 100644 SQL/mysql_indexing_best_practices.md diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md new file mode 100644 index 0000000..9e924d7 --- /dev/null +++ b/SQL/mysql_indexing_best_practices.md @@ -0,0 +1,173 @@ + +MySQL Indexing Best Practices + + +TL;DR This story is going to be a bit longer than usual because the topic demands it’s so. Before jumping into the nitty-gritty of indexing your MySQL query, I think its good to share how I am worthful (which I think :-)) to create such a story. During my work tenure, I got a chance to work with MySQL databases having data size up to 700 Million. I know these numbers are way small. Even though, I am sharing you guys how I indexed and optimized queries. I will be emphasizing more on how to index rather than what is an index and why it’s required. + +When you should Optimize MySQL database? +Ideally, query performance tuning should happen regularly. +Indexing is not a one-time process. It is advised to conduct weekly or monthly checks of database performance to prevent issues adversely affecting your applications. +The most obvious symptoms of performance problems are: +Queries take a longer execution time than anticipated. +Applications using the database become slower than usual. +Connection timeouts errors. +It is normal to have several concurrent queries running at one time on a busy system, but it becomes a problem when these queries are taking too long to finish. +How will you recognise which of your queries performing adversely?. +Grasping which of your MySQL query gone crazy is essential in diagnosing the performance issue. Let me introduce two ways which are your friends in identifying the queries which caused the performance bottleneck. +MySQL Slow query log. Enable it. +processlist. Use it. + +show processlist; +show full processlist; + +How you will identify whether the query lacks an index?. +Now you understood which are those troublemakers in the application. But, how will you recognise that they perform adversely only due to lack of an index?. Well, EXPLAIN statement of MySQL can be your lifesaver. +EXPLAIN is used to obtain a query execution plan (that is, an explanation of how MySQL would execute a query). +EXPLAIN works with SELECT, DELETE, REPLACE, and UPDATE (From Mysql version 5.7 onwards) statements. Just like you, MySQL will have amazing plans for each query on how to execute, which index to pick, how to join tables and which order it should maintain for optimal performance. +Check out the below table description, I want you to memorise this table as it will be using in most of my examples. The table doesn’t have any index at present. +Table description +Let’s take a sample query and analyse what EXPLAIN yields to it. + +select * from master_users where email="akhil@gmail.com" + +Explaining the above query gives as… + +Before Index +Let’s breakdown the EXPLAIN result. As you can see MySQL had traversed through 152685 rows (See the column: rows) of the table to find a matching row and its equal to a full table scan because the table has 153728 rows in total. EXPLAIN result has two columns with names as possible keys and key. possible_keys column tells us what are the available indexes in a table or the indexes which may be used for our queries. keys column tells us what are the indexes that MySQL used for the analyzed query. As of now, both are empty. An empty key column provides you with the information that the query lacks an index. +Let’s add one index and examine what happens. +ALTER TABLE master_users ADD INDEX index_email(email) +After adding an index. +Now you can see that the query is better optimized and MySQL was able to find a matching result without traversing many rows. If you notice, we have our index name present in both of the columns possible_keys and key. +You optimized a simple query but mine is a complex one!!! +I know that the query optimized just now is a piece of cake for you. Before jumping into more complex queries, I want you to learn the Rule of Thumb in indexing. +MySQL can only use one index per each of the tables in a query (Exemptions are there. eg, Merging of indexes). Which ideally means that a table in a query, must use a single index for all where-clause, table join, group-by and order-by. +Believe me, learning this rule was a breakthrough in my career. I used to believe that, it’s required to add an individual single index on each of the columns used in WHERE clause, JOIN clause, group-by and order-by. +Let’s take another query. +select * from master_users where email="akhil@gmail.com" and category_id=3 +Keeping the rule of thumb in mind, you already know that creating two indexes on email and category will not help. +If separate single-column indexes exist on col1 and col2, MySQL optimizer attempts to use the Index Merge optimization or attempts to find the most restrictive index by deciding which index excludes more rows and using that index to fetch the rows. +Now, what you will do?. A multiple column (composite) index to the rescue..! +Composite index or Multiple columns index +To optimize such queries, you should create a composite or compound index. A composite index can be described as a compound of multiple columns. +By adding several columns into an index you can narrow down the number of rows MySQL has to traverse to find matching rows. An index may consist of up to 16 columns. +Let’s see, how you can create a composite index. +ALTER TABLE ADD INDEX index_co1_col2(column1, column2, column3,...) +Does the column’s order matters in a compound index?. +Yes, it does matters. A column which is having the least cardinality value (Having less number of distinctive values) should always be positioned as the left-most side in a composite index. Order of precedence of other columns also dependent on the cardinality of respective columns. +Now, How will you find the cardinality or number of distinct values of a column?. You can just perform a distinctive count query on the column. (It’s advised not to perform such queries mentioned below in a production DB when it is running in the peak time of traffic.) +select count(distinct(email)) from master_users +select count(distinct(category_id)) from master_users +Distinctive counts of each column +Here you can see that the cardinality of the category_id column is less than that of email column so that we should create a composite index just as follows. +ALTER TABLE master_users ADD INDEX index_category_email(category_id, email) +As you observe the order in which these columns are indexed, and thus how they are sorted will restrict the usage of our index to some particular queries only. +As an example, the index we’ve just created (category_id, email) would not be beneficial for a query such as: +select * from master_users where email=”akhil@gmail.com” +Why? Just now you said that a composite index will be beneficial for mine query. +Well, there is a reason for it. +If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to look up rows. For example, if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3). +This means that MySQL optimizer can’t use an index to perform lookups if the query doesn’t contain the leftmost prefix column of the index. So the left-most column in a composite index is known as the Lookup column. +MySQL can use multiple-column indexes for queries that test all the columns in the index, or queries that test just the first column, the first two columns, the first three columns, and so on. If you specify the columns in the right order in the index definition, a single composite index can speed up several kinds of queries on the same table. +In the above query, I used email as the only WHERE clause term, hence composite index won’t be useful as it lacks lookup column of the index. +There is another advantage for the composite index; If an index exists on (col1, col2, col3), the same index can be equivalent to creating multiple indexes like an index on col1, index on (col1,col2) and index on (col1,col2,col3) provided index order matters. +if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3) +For example, let’s take an index (status, category_id, email). This index will be useful in below queries. + +select * from master_users where status=1 +select * from master_users where status=1 and category_id=3 +select * from master_users where status=1 and category_id=3 and email="akhil@gmail.com" + +But not in the below queries; + +select * from master_users where category_id=3 +select * from master_users where category_id=3 and email="akhil@gmail.com" + +What if your query contains OR operator instead of AND?. +select status,category_id from master_users where status=1 or category_id=3 +In this case, MySQL won’t be able to use the index on queries having an OR condition, even if the query contains lookup column and maintains the order of WHERE clause same as the index. +Therefore, it’s recommended to avoid such OR conditions and consider splitting the query to two parts, combined with a UNION DISTINCT (or even better, UNION ALL, in case you know there won’t be any duplicate results) +select status,category_id from master_users where status=1 +UNION ALL +select status,category_id from master_users where category_id=3 +What if your query contains GROUP BY and ORDER BY +let’s take the same index (status, category_id, email), and you run the query: + +select * from master_users where status=1 ORDER BY category_id + +This will use the composite index for the WHERE clause and if you think this will narrow down the records with the status having value as 1, sadly you now need to perform a sort on these resulting records to get them sorted by category_id. This is because the index didn’t sort the results by category_id in any meaningful way and ORDER BY clause lacks the lookup column. +This is known as a File Sort (some of you might have noticed this in an explain result). This happens because the index that we created failed to satisfy for the ORDER BY clause. +File Sort: A sort that occurs after the query; it requires fetching the data into a temporary buffer and sorting it before finally returning. This wouldn’t have been needed if the data was already sorted by the index in the way you wanted. +This also applies even If you only wanted to read 10 rows. +select * from master_users where status=1 ORDER BY category_id limit 5 +You’ll still be fetching thousands of records, sorting them, and only after this, returning the top 5 while discarding the rest of the records you spent time processing. + +select * from master_users where status=1 ORDER BY status, category_id + +This query can leverage the usage of the mentioned index because it qualifies for both the WHERE clause and ORDER BY clause. +Consider another query, which sorts rows by the status in ascending order, and then by the category_id in descending order. +select * from master_users where status=1 ORDER BY status ASC, category_id DESC +MySQL cannot use indexes when sorting with a mixed order (both ASC and DESC in the same ORDER BY clause). +Note: This changed with the release of the reversed indexes functionality and MySQL 8.x. +Whatever you saw against ORDER BY is also applicable to GROUP BY statements. if you run the following query with the composite index on (status, category_id, email): + +select * from master_users where status=1 GROUP BY category_id + +The records are already sorted by status, category_id and email. This allows you to quickly filter down all the records with status=1. After these results are returned they are also then sorted based on category_id since the index orders the rows differently than required in the query. +What if your query contains JOINS?. +You should have indexes on all the columns used in the JOIN clauses. i.e, columns on each side of ON clause of a join must be indexed. +What if your query contains RANGE conditions?. +A query is treated as a Range query if it uses any or mix of following operators; +=, <=>, IN(), IS NULL, or IS NOT NULL, >, <, >=, <=, BETWEEN, !=, or <> operators, or LIKE comparisons (If the argument to LIKE is a constant string that does not start with a wildcard character.) +If you’re utilizing an index for range queries, try to make sure the column you’re specifying the range operator is ordered last within the index. You should only add one of them for each table — the most selective condition, as MySQL can only handle one ‘ranged column’ in each index + +So what columns should I Index? +You should realize from all that we’ve discussed that it depends… +What columns you’re going to query +What JOINs you’ll perform +What ORDER/GROUP BYs etc. + +A bonus topic: Covering Index +Before understanding what a covering index Is, let’s learn how MySQL fetch matching rows for a query. +A MySQL select query consists of two phases. A query phase and a fetch phase. In the query phase, MySQL tries to find primary key values of all matching rows using the index. In the fetch phase, MySQL uses these retrieved primary keys to fetch the actual row values. +If you have a MySQL with InnoDB engine, you will commonly use indexes such as Clustered index and secondary index. +When you define a PRIMARY KEY on your table, InnoDB uses it as the clustered index. InnoDB table storage is organized based on the values of the primary key columns, to speed up queries and sorts involving the primary key columns. All indexes other than the clustered index are known as secondary indexes. +Now the main point here is, +In InnoDB, each record in a secondary index contains the primary key columns for the row, as well as the columns specified for the secondary index. InnoDB uses this primary key value to search for the row in the clustered index. +So, MySQL has to depend on the Primary Key index to perform the fetch phase even if all the matching rows are identified using an index (Secondary index). +select mobile from master_users where mode=2 +Consider the above query and assume you have created an index on ‘mode’. +MySQL can easily retrieve the Primary Key values for all the records with mode value as 2, however, to fetch the mobile column, MySQL would still need to use the primary key values to fetch row data from the Primary Key index. +Now, what if we add an index like this, +ALTER TABLE master_users ADD INDEX index_covering(mode, mobile) +Using above index, MySQL can easily retrieve the Primary Key values for all the records with mode value as 2, and to fetch the mobile column, MySQL no need to depend on the Primary Key index to fetch row data. Above query is completely covered by the index and hence known as a covering index. +The ideal database design uses a covering index where practical; the query results are computed entirely from the index, without reading the actual table data. + +The Dos and Don’ts of Database Indexing + +Do not create indexes unless you know you’ll need them. +Don’t index each column in the table separately. +Avoid using functions on the Left Hand-Side of the Operator. +Eg: select * from master_users where upper(email)="AKHIL@GMAIL.COM" +If you use a function in the left-hand side of the operator then MySQL won't use index even if the column has an index on it. +But, it’s ok to have a function in the right hand +Eg: select * from master_users where created < now() +Avoid Wildcard Characters at the Beginning of a LIKE Pattern. +Don't: select * from master_users where email LIKE "%akhil%" +Dos: select * from master_users where email LIKE "akhil%" +MySQL won't use an index for wildcard searches +Avoid OR conditions and use UNION as an alternative. +Avoid sorting with a mixed order. +Don't: select * from master_users where status=1 ORDER BY status ASC, category_id DESC +Dos: select * from master_users where status=1 ORDER BY status ASC, category_id ASC +In where clause, compare a column to a value which matches the column’s type. +Don't: select * from master_users where email=101 +Dos: select * from master_users where email="101" +Columns on each side of ON clause of a join must be of the same type. +If columns on each side of ON clause of a join is VARCHAR, make sure the collations of each of the columns are identical. +You do not want to place too many indexes on tables that are frequently updated +Keep your table statistics up to date. +This is done with ANALYZE TABLE table_name + +Create indexes, but do it wisely. Happy indexing…!!! + + From 337f2b8662c6e7d03d503b226575ca08c7f9a948 Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Fri, 2 Oct 2020 18:04:51 +0530 Subject: [PATCH 02/14] Update mysql_indexing_best_practices.md Content formatting --- SQL/mysql_indexing_best_practices.md | 157 ++++++++++++++++++++------- 1 file changed, 116 insertions(+), 41 deletions(-) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index 9e924d7..656d6df 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -5,15 +5,21 @@ MySQL Indexing Best Practices TL;DR This story is going to be a bit longer than usual because the topic demands it’s so. Before jumping into the nitty-gritty of indexing your MySQL query, I think its good to share how I am worthful (which I think :-)) to create such a story. During my work tenure, I got a chance to work with MySQL databases having data size up to 700 Million. I know these numbers are way small. Even though, I am sharing you guys how I indexed and optimized queries. I will be emphasizing more on how to index rather than what is an index and why it’s required. When you should Optimize MySQL database? + Ideally, query performance tuning should happen regularly. Indexing is not a one-time process. It is advised to conduct weekly or monthly checks of database performance to prevent issues adversely affecting your applications. The most obvious symptoms of performance problems are: -Queries take a longer execution time than anticipated. -Applications using the database become slower than usual. -Connection timeouts errors. -It is normal to have several concurrent queries running at one time on a busy system, but it becomes a problem when these queries are taking too long to finish. +- Queries take a longer execution time than anticipated. +- Applications using the database become slower than usual. +- Connection timeouts errors. +- It is normal to have several concurrent queries running at one time on a busy system, but it becomes a problem when these queries are taking too long to finish. + How will you recognise which of your queries performing adversely?. -Grasping which of your MySQL query gone crazy is essential in diagnosing the performance issue. Let me introduce two ways which are your friends in identifying the queries which caused the performance bottleneck. + +Grasping which of your MySQL query gone crazy is essential in diagnosing the performance issue. + +Let me introduce two ways which are your friends in identifying the queries which caused the performance bottleneck. + MySQL Slow query log. Enable it. processlist. Use it. @@ -21,11 +27,18 @@ show processlist; show full processlist; How you will identify whether the query lacks an index?. -Now you understood which are those troublemakers in the application. But, how will you recognise that they perform adversely only due to lack of an index?. Well, EXPLAIN statement of MySQL can be your lifesaver. + +Now you understood which are those troublemakers in the application. But, how will you recognise that they perform adversely only due to lack of an index?. +Well, EXPLAIN statement of MySQL can be your lifesaver. + EXPLAIN is used to obtain a query execution plan (that is, an explanation of how MySQL would execute a query). -EXPLAIN works with SELECT, DELETE, REPLACE, and UPDATE (From Mysql version 5.7 onwards) statements. Just like you, MySQL will have amazing plans for each query on how to execute, which index to pick, how to join tables and which order it should maintain for optimal performance. -Check out the below table description, I want you to memorise this table as it will be using in most of my examples. The table doesn’t have any index at present. +EXPLAIN works with SELECT, DELETE, REPLACE, and UPDATE (From Mysql version 5.7 onwards) statements. +Just like you, MySQL will have amazing plans for each query on how to execute, which index to pick, how to join tables and which order it should maintain for optimal performance. + +Check out the below table description, I want you to memorise this table as it will be using in most of my examples. +The table doesn’t have any index at present. Table description + Let’s take a sample query and analyse what EXPLAIN yields to it. select * from master_users where email="akhil@gmail.com" @@ -33,43 +46,81 @@ select * from master_users where email="akhil@gmail.com" Explaining the above query gives as… Before Index -Let’s breakdown the EXPLAIN result. As you can see MySQL had traversed through 152685 rows (See the column: rows) of the table to find a matching row and its equal to a full table scan because the table has 153728 rows in total. EXPLAIN result has two columns with names as possible keys and key. possible_keys column tells us what are the available indexes in a table or the indexes which may be used for our queries. keys column tells us what are the indexes that MySQL used for the analyzed query. As of now, both are empty. An empty key column provides you with the information that the query lacks an index. +Let’s breakdown the EXPLAIN result. + +As you can see MySQL had traversed through 152685 rows (See the column: rows) of the table to find a matching row and its equal to a full table scan because the table has 153728 rows in total. +EXPLAIN result has two columns with names as possible keys and key. possible_keys column tells us what are the available indexes in a table or the indexes which may be used for our queries. keys column tells us what are the indexes that MySQL used for the analyzed query. +As of now, both are empty. An empty key column provides you with the information that the query lacks an index. + Let’s add one index and examine what happens. ALTER TABLE master_users ADD INDEX index_email(email) + After adding an index. -Now you can see that the query is better optimized and MySQL was able to find a matching result without traversing many rows. If you notice, we have our index name present in both of the columns possible_keys and key. + +Now you can see that the query is better optimized and MySQL was able to find a matching result without traversing many rows. +If you notice, we have our index name present in both of the columns possible_keys and key. + You optimized a simple query but mine is a complex one!!! -I know that the query optimized just now is a piece of cake for you. Before jumping into more complex queries, I want you to learn the Rule of Thumb in indexing. -MySQL can only use one index per each of the tables in a query (Exemptions are there. eg, Merging of indexes). Which ideally means that a table in a query, must use a single index for all where-clause, table join, group-by and order-by. + +I know that the query optimized just now is a piece of cake for you. Before jumping into more complex queries, +I want you to learn the Rule of Thumb in indexing. + +MySQL can only use one index per each of the tables in a query (Exemptions are there. eg, Merging of indexes). +Which ideally means that a table in a query, must use a single index for all where-clause, table join, group-by and order-by. + Believe me, learning this rule was a breakthrough in my career. I used to believe that, it’s required to add an individual single index on each of the columns used in WHERE clause, JOIN clause, group-by and order-by. + Let’s take another query. select * from master_users where email="akhil@gmail.com" and category_id=3 + Keeping the rule of thumb in mind, you already know that creating two indexes on email and category will not help. If separate single-column indexes exist on col1 and col2, MySQL optimizer attempts to use the Index Merge optimization or attempts to find the most restrictive index by deciding which index excludes more rows and using that index to fetch the rows. -Now, what you will do?. A multiple column (composite) index to the rescue..! +Now, what you will do?. + +A multiple column (composite) index to the rescue..! Composite index or Multiple columns index + To optimize such queries, you should create a composite or compound index. A composite index can be described as a compound of multiple columns. By adding several columns into an index you can narrow down the number of rows MySQL has to traverse to find matching rows. An index may consist of up to 16 columns. + Let’s see, how you can create a composite index. + ALTER TABLE ADD INDEX index_co1_col2(column1, column2, column3,...) + Does the column’s order matters in a compound index?. -Yes, it does matters. A column which is having the least cardinality value (Having less number of distinctive values) should always be positioned as the left-most side in a composite index. Order of precedence of other columns also dependent on the cardinality of respective columns. + +Yes, it does matters. +A column which is having the least cardinality value (Having less number of distinctive values) should always be positioned as the left-most side in a composite index. +Order of precedence of other columns also dependent on the cardinality of respective columns. + Now, How will you find the cardinality or number of distinct values of a column?. You can just perform a distinctive count query on the column. (It’s advised not to perform such queries mentioned below in a production DB when it is running in the peak time of traffic.) + select count(distinct(email)) from master_users select count(distinct(category_id)) from master_users + Distinctive counts of each column + Here you can see that the cardinality of the category_id column is less than that of email column so that we should create a composite index just as follows. + ALTER TABLE master_users ADD INDEX index_category_email(category_id, email) + As you observe the order in which these columns are indexed, and thus how they are sorted will restrict the usage of our index to some particular queries only. + As an example, the index we’ve just created (category_id, email) would not be beneficial for a query such as: + select * from master_users where email=”akhil@gmail.com” + Why? Just now you said that a composite index will be beneficial for mine query. Well, there is a reason for it. -If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to look up rows. For example, if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3). + +If the table has a multiple-column index, any leftmost prefix of the index can be used by the optimizer to look up rows. +For example, if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3). This means that MySQL optimizer can’t use an index to perform lookups if the query doesn’t contain the leftmost prefix column of the index. So the left-most column in a composite index is known as the Lookup column. MySQL can use multiple-column indexes for queries that test all the columns in the index, or queries that test just the first column, the first two columns, the first three columns, and so on. If you specify the columns in the right order in the index definition, a single composite index can speed up several kinds of queries on the same table. + In the above query, I used email as the only WHERE clause term, hence composite index won’t be useful as it lacks lookup column of the index. There is another advantage for the composite index; If an index exists on (col1, col2, col3), the same index can be equivalent to creating multiple indexes like an index on col1, index on (col1,col2) and index on (col1,col2,col3) provided index order matters. + if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3) For example, let’s take an index (status, category_id, email). This index will be useful in below queries. @@ -83,41 +134,59 @@ select * from master_users where category_id=3 select * from master_users where category_id=3 and email="akhil@gmail.com" What if your query contains OR operator instead of AND?. + select status,category_id from master_users where status=1 or category_id=3 In this case, MySQL won’t be able to use the index on queries having an OR condition, even if the query contains lookup column and maintains the order of WHERE clause same as the index. Therefore, it’s recommended to avoid such OR conditions and consider splitting the query to two parts, combined with a UNION DISTINCT (or even better, UNION ALL, in case you know there won’t be any duplicate results) + select status,category_id from master_users where status=1 UNION ALL select status,category_id from master_users where category_id=3 + What if your query contains GROUP BY and ORDER BY + let’s take the same index (status, category_id, email), and you run the query: select * from master_users where status=1 ORDER BY category_id This will use the composite index for the WHERE clause and if you think this will narrow down the records with the status having value as 1, sadly you now need to perform a sort on these resulting records to get them sorted by category_id. This is because the index didn’t sort the results by category_id in any meaningful way and ORDER BY clause lacks the lookup column. + This is known as a File Sort (some of you might have noticed this in an explain result). This happens because the index that we created failed to satisfy for the ORDER BY clause. File Sort: A sort that occurs after the query; it requires fetching the data into a temporary buffer and sorting it before finally returning. This wouldn’t have been needed if the data was already sorted by the index in the way you wanted. + This also applies even If you only wanted to read 10 rows. + select * from master_users where status=1 ORDER BY category_id limit 5 + You’ll still be fetching thousands of records, sorting them, and only after this, returning the top 5 while discarding the rest of the records you spent time processing. select * from master_users where status=1 ORDER BY status, category_id This query can leverage the usage of the mentioned index because it qualifies for both the WHERE clause and ORDER BY clause. + Consider another query, which sorts rows by the status in ascending order, and then by the category_id in descending order. + select * from master_users where status=1 ORDER BY status ASC, category_id DESC + MySQL cannot use indexes when sorting with a mixed order (both ASC and DESC in the same ORDER BY clause). + Note: This changed with the release of the reversed indexes functionality and MySQL 8.x. + Whatever you saw against ORDER BY is also applicable to GROUP BY statements. if you run the following query with the composite index on (status, category_id, email): select * from master_users where status=1 GROUP BY category_id The records are already sorted by status, category_id and email. This allows you to quickly filter down all the records with status=1. After these results are returned they are also then sorted based on category_id since the index orders the rows differently than required in the query. + What if your query contains JOINS?. + You should have indexes on all the columns used in the JOIN clauses. i.e, columns on each side of ON clause of a join must be indexed. + What if your query contains RANGE conditions?. + A query is treated as a Range query if it uses any or mix of following operators; =, <=>, IN(), IS NULL, or IS NOT NULL, >, <, >=, <=, BETWEEN, !=, or <> operators, or LIKE comparisons (If the argument to LIKE is a constant string that does not start with a wildcard character.) + If you’re utilizing an index for range queries, try to make sure the column you’re specifying the range operator is ordered last within the index. You should only add one of them for each table — the most selective condition, as MySQL can only handle one ‘ranged column’ in each index So what columns should I Index? @@ -127,47 +196,53 @@ What JOINs you’ll perform What ORDER/GROUP BYs etc. A bonus topic: Covering Index + Before understanding what a covering index Is, let’s learn how MySQL fetch matching rows for a query. -A MySQL select query consists of two phases. A query phase and a fetch phase. In the query phase, MySQL tries to find primary key values of all matching rows using the index. In the fetch phase, MySQL uses these retrieved primary keys to fetch the actual row values. +A MySQL select query consists of two phases. +A query phase and a fetch phase. In the query phase, MySQL tries to find primary key values of all matching rows using the index. In the fetch phase, MySQL uses these retrieved primary keys to fetch the actual row values. + If you have a MySQL with InnoDB engine, you will commonly use indexes such as Clustered index and secondary index. When you define a PRIMARY KEY on your table, InnoDB uses it as the clustered index. InnoDB table storage is organized based on the values of the primary key columns, to speed up queries and sorts involving the primary key columns. All indexes other than the clustered index are known as secondary indexes. Now the main point here is, + In InnoDB, each record in a secondary index contains the primary key columns for the row, as well as the columns specified for the secondary index. InnoDB uses this primary key value to search for the row in the clustered index. So, MySQL has to depend on the Primary Key index to perform the fetch phase even if all the matching rows are identified using an index (Secondary index). select mobile from master_users where mode=2 Consider the above query and assume you have created an index on ‘mode’. + MySQL can easily retrieve the Primary Key values for all the records with mode value as 2, however, to fetch the mobile column, MySQL would still need to use the primary key values to fetch row data from the Primary Key index. + Now, what if we add an index like this, + ALTER TABLE master_users ADD INDEX index_covering(mode, mobile) + Using above index, MySQL can easily retrieve the Primary Key values for all the records with mode value as 2, and to fetch the mobile column, MySQL no need to depend on the Primary Key index to fetch row data. Above query is completely covered by the index and hence known as a covering index. The ideal database design uses a covering index where practical; the query results are computed entirely from the index, without reading the actual table data. The Dos and Don’ts of Database Indexing -Do not create indexes unless you know you’ll need them. -Don’t index each column in the table separately. -Avoid using functions on the Left Hand-Side of the Operator. -Eg: select * from master_users where upper(email)="AKHIL@GMAIL.COM" -If you use a function in the left-hand side of the operator then MySQL won't use index even if the column has an index on it. -But, it’s ok to have a function in the right hand -Eg: select * from master_users where created < now() -Avoid Wildcard Characters at the Beginning of a LIKE Pattern. -Don't: select * from master_users where email LIKE "%akhil%" -Dos: select * from master_users where email LIKE "akhil%" -MySQL won't use an index for wildcard searches -Avoid OR conditions and use UNION as an alternative. -Avoid sorting with a mixed order. -Don't: select * from master_users where status=1 ORDER BY status ASC, category_id DESC -Dos: select * from master_users where status=1 ORDER BY status ASC, category_id ASC -In where clause, compare a column to a value which matches the column’s type. -Don't: select * from master_users where email=101 -Dos: select * from master_users where email="101" -Columns on each side of ON clause of a join must be of the same type. -If columns on each side of ON clause of a join is VARCHAR, make sure the collations of each of the columns are identical. -You do not want to place too many indexes on tables that are frequently updated -Keep your table statistics up to date. -This is done with ANALYZE TABLE table_name +- Do not create indexes unless you know you’ll need them. +- Don’t index each column in the table separately. +- Avoid using functions on the Left Hand-Side of the Operator. + Eg: select * from master_users where upper(email)="AKHIL@GMAIL.COM" +- If you use a function in the left-hand side of the operator then MySQL won't use index even if the column has an index on it. + But, it’s ok to have a function in the right hand + Eg: select * from master_users where created < now() +- Avoid Wildcard Characters at the Beginning of a LIKE Pattern. + Don't: select * from master_users where email LIKE "%akhil%" + Dos: select * from master_users where email LIKE "akhil%" +- MySQL won't use an index for wildcard searches +- Avoid OR conditions and use UNION as an alternative. +- Avoid sorting with a mixed order. + Don't: select * from master_users where status=1 ORDER BY status ASC, category_id DESC + Dos: select * from master_users where status=1 ORDER BY status ASC, category_id ASC +- In where clause, compare a column to a value which matches the column’s type. + Don't: select * from master_users where email=101 + Dos: select * from master_users where email="101" +- Columns on each side of ON clause of a join must be of the same type. +- If columns on each side of ON clause of a join is VARCHAR, make sure the collations of each of the columns are identical. +- You do not want to place too many indexes on tables that are frequently updated +- Keep your table statistics up to date. + This is done with ANALYZE TABLE table_name Create indexes, but do it wisely. Happy indexing…!!! - - From 21c363a65354b07b819794e8fa4f1c098b3dab8d Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Fri, 2 Oct 2020 18:09:43 +0530 Subject: [PATCH 03/14] Added description --- SQL/mysql_indexing_best_practices.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index 656d6df..fbafb04 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -1,5 +1,6 @@ - -MySQL Indexing Best Practices +--- +Create indexes, but do it wisely. In this tutorial, I will explain the best practices that developers can implement for their MySQL performance tuning efforts. This tutorial will focus on MySQL query performance tuning with the help of index with practical examples. +--- TL;DR This story is going to be a bit longer than usual because the topic demands it’s so. Before jumping into the nitty-gritty of indexing your MySQL query, I think its good to share how I am worthful (which I think :-)) to create such a story. During my work tenure, I got a chance to work with MySQL databases having data size up to 700 Million. I know these numbers are way small. Even though, I am sharing you guys how I indexed and optimized queries. I will be emphasizing more on how to index rather than what is an index and why it’s required. From 6b0d272ebc7d860e1bc3c11b0dd120bc2c983a42 Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Fri, 2 Oct 2020 18:10:46 +0530 Subject: [PATCH 04/14] Update mysql_indexing_best_practices.md --- SQL/mysql_indexing_best_practices.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index fbafb04..a5249c6 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -1,4 +1,6 @@ --- +Author: Akhil Mathew +Title: MySQL indexing best practices. Create indexes, but do it wisely. In this tutorial, I will explain the best practices that developers can implement for their MySQL performance tuning efforts. This tutorial will focus on MySQL query performance tuning with the help of index with practical examples. --- From 046813433abbd167462827084e80ceecf8ac9c10 Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Fri, 2 Oct 2020 18:11:25 +0530 Subject: [PATCH 05/14] Update mysql_indexing_best_practices.md --- SQL/mysql_indexing_best_practices.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index a5249c6..fdddadb 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -1,7 +1,7 @@ ---- Author: Akhil Mathew Title: MySQL indexing best practices. -Create indexes, but do it wisely. In this tutorial, I will explain the best practices that developers can implement for their MySQL performance tuning efforts. This tutorial will focus on MySQL query performance tuning with the help of index with practical examples. +Create indexes, but do it wisely. +In this tutorial, I will explain the best practices that developers can implement for their MySQL performance tuning efforts. --- From 79d222d2c6128e5f5f5fda74885f27da6db3b917 Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Fri, 2 Oct 2020 18:11:46 +0530 Subject: [PATCH 06/14] Update mysql_indexing_best_practices.md --- SQL/mysql_indexing_best_practices.md | 1 + 1 file changed, 1 insertion(+) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index fdddadb..8800805 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -1,3 +1,4 @@ +--- Author: Akhil Mathew Title: MySQL indexing best practices. Create indexes, but do it wisely. From edd30091c59119154727dfbb4fb72016fcf32fba Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Fri, 2 Oct 2020 18:12:19 +0530 Subject: [PATCH 07/14] Update mysql_indexing_best_practices.md --- SQL/mysql_indexing_best_practices.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index 8800805..56101e8 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -1,8 +1,9 @@ --- Author: Akhil Mathew Title: MySQL indexing best practices. -Create indexes, but do it wisely. -In this tutorial, I will explain the best practices that developers can implement for their MySQL performance tuning efforts. +Description: Create indexes, but do it wisely. +In this tutorial, I will explain the best practices that developers can implement +for their MySQL performance tuning efforts. --- From 952c341f866bc802ac773fb78112b47276cbfb63 Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Sat, 10 Oct 2020 12:02:58 +0530 Subject: [PATCH 08/14] Text highlighting --- SQL/mysql_indexing_best_practices.md | 32 +++++++++++++++------------- 1 file changed, 17 insertions(+), 15 deletions(-) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index 56101e8..458c43f 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -9,7 +9,7 @@ for their MySQL performance tuning efforts. TL;DR This story is going to be a bit longer than usual because the topic demands it’s so. Before jumping into the nitty-gritty of indexing your MySQL query, I think its good to share how I am worthful (which I think :-)) to create such a story. During my work tenure, I got a chance to work with MySQL databases having data size up to 700 Million. I know these numbers are way small. Even though, I am sharing you guys how I indexed and optimized queries. I will be emphasizing more on how to index rather than what is an index and why it’s required. -When you should Optimize MySQL database? +**When you should Optimize MySQL database?** Ideally, query performance tuning should happen regularly. Indexing is not a one-time process. It is advised to conduct weekly or monthly checks of database performance to prevent issues adversely affecting your applications. @@ -19,7 +19,7 @@ The most obvious symptoms of performance problems are: - Connection timeouts errors. - It is normal to have several concurrent queries running at one time on a busy system, but it becomes a problem when these queries are taking too long to finish. -How will you recognise which of your queries performing adversely?. +**How will you recognise which of your queries performing adversely?.** Grasping which of your MySQL query gone crazy is essential in diagnosing the performance issue. @@ -31,7 +31,7 @@ processlist. Use it. show processlist; show full processlist; -How you will identify whether the query lacks an index?. +**How you will identify whether the query lacks an index?.** Now you understood which are those troublemakers in the application. But, how will you recognise that they perform adversely only due to lack of an index?. Well, EXPLAIN statement of MySQL can be your lifesaver. @@ -44,7 +44,7 @@ Check out the below table description, I want you to memorise this table as it w The table doesn’t have any index at present. Table description -Let’s take a sample query and analyse what EXPLAIN yields to it. +**Let’s take a sample query and analyse what EXPLAIN yields to it.** select * from master_users where email="akhil@gmail.com" @@ -65,7 +65,7 @@ After adding an index. Now you can see that the query is better optimized and MySQL was able to find a matching result without traversing many rows. If you notice, we have our index name present in both of the columns possible_keys and key. -You optimized a simple query but mine is a complex one!!! +**You optimized a simple query but mine is a complex one!!!** I know that the query optimized just now is a piece of cake for you. Before jumping into more complex queries, I want you to learn the Rule of Thumb in indexing. @@ -82,7 +82,8 @@ Keeping the rule of thumb in mind, you already know that creating two indexes on If separate single-column indexes exist on col1 and col2, MySQL optimizer attempts to use the Index Merge optimization or attempts to find the most restrictive index by deciding which index excludes more rows and using that index to fetch the rows. Now, what you will do?. -A multiple column (composite) index to the rescue..! +**multiple column (composite) index to the rescue..!** + Composite index or Multiple columns index To optimize such queries, you should create a composite or compound index. A composite index can be described as a compound of multiple columns. @@ -92,7 +93,7 @@ Let’s see, how you can create a composite index. ALTER TABLE ADD INDEX index_co1_col2(column1, column2, column3,...) -Does the column’s order matters in a compound index?. +**Does the column’s order matters in a compound index?.** Yes, it does matters. A column which is having the least cardinality value (Having less number of distinctive values) should always be positioned as the left-most side in a composite index. @@ -138,7 +139,7 @@ But not in the below queries; select * from master_users where category_id=3 select * from master_users where category_id=3 and email="akhil@gmail.com" -What if your query contains OR operator instead of AND?. +**What if your query contains OR operator instead of AND?.** select status,category_id from master_users where status=1 or category_id=3 In this case, MySQL won’t be able to use the index on queries having an OR condition, even if the query contains lookup column and maintains the order of WHERE clause same as the index. @@ -148,7 +149,7 @@ select status,category_id from master_users where status=1 UNION ALL select status,category_id from master_users where category_id=3 -What if your query contains GROUP BY and ORDER BY +**What if your query contains GROUP BY and ORDER BY** let’s take the same index (status, category_id, email), and you run the query: @@ -183,24 +184,25 @@ select * from master_users where status=1 GROUP BY category_id The records are already sorted by status, category_id and email. This allows you to quickly filter down all the records with status=1. After these results are returned they are also then sorted based on category_id since the index orders the rows differently than required in the query. -What if your query contains JOINS?. +**What if your query contains JOINS?.** You should have indexes on all the columns used in the JOIN clauses. i.e, columns on each side of ON clause of a join must be indexed. -What if your query contains RANGE conditions?. +**What if your query contains RANGE conditions?.** A query is treated as a Range query if it uses any or mix of following operators; =, <=>, IN(), IS NULL, or IS NOT NULL, >, <, >=, <=, BETWEEN, !=, or <> operators, or LIKE comparisons (If the argument to LIKE is a constant string that does not start with a wildcard character.) If you’re utilizing an index for range queries, try to make sure the column you’re specifying the range operator is ordered last within the index. You should only add one of them for each table — the most selective condition, as MySQL can only handle one ‘ranged column’ in each index -So what columns should I Index? +**So what columns should I Index?** + You should realize from all that we’ve discussed that it depends… What columns you’re going to query What JOINs you’ll perform What ORDER/GROUP BYs etc. -A bonus topic: Covering Index +**A bonus topic: Covering Index** Before understanding what a covering index Is, let’s learn how MySQL fetch matching rows for a query. A MySQL select query consists of two phases. @@ -224,7 +226,7 @@ ALTER TABLE master_users ADD INDEX index_covering(mode, mobile) Using above index, MySQL can easily retrieve the Primary Key values for all the records with mode value as 2, and to fetch the mobile column, MySQL no need to depend on the Primary Key index to fetch row data. Above query is completely covered by the index and hence known as a covering index. The ideal database design uses a covering index where practical; the query results are computed entirely from the index, without reading the actual table data. -The Dos and Don’ts of Database Indexing +**The Dos and Don’ts of Database Indexing** - Do not create indexes unless you know you’ll need them. - Don’t index each column in the table separately. @@ -250,4 +252,4 @@ The Dos and Don’ts of Database Indexing - Keep your table statistics up to date. This is done with ANALYZE TABLE table_name -Create indexes, but do it wisely. Happy indexing…!!! +*Create indexes, but do it wisely. Happy indexing…!!!* From 5d94b2dc9d90aa69fad6ab8ee67bd2b5aabf2c06 Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Sat, 10 Oct 2020 12:07:48 +0530 Subject: [PATCH 09/14] Query highlighting --- SQL/mysql_indexing_best_practices.md | 49 +++++++++++++++++++++++++--- 1 file changed, 44 insertions(+), 5 deletions(-) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index 458c43f..1ca7f4b 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -28,15 +28,17 @@ Let me introduce two ways which are your friends in identifying the queries whic MySQL Slow query log. Enable it. processlist. Use it. +``` show processlist; show full processlist; +``` **How you will identify whether the query lacks an index?.** Now you understood which are those troublemakers in the application. But, how will you recognise that they perform adversely only due to lack of an index?. Well, EXPLAIN statement of MySQL can be your lifesaver. -EXPLAIN is used to obtain a query execution plan (that is, an explanation of how MySQL would execute a query). +**EXPLAIN** is used to obtain a query execution plan (that is, an explanation of how MySQL would execute a query). EXPLAIN works with SELECT, DELETE, REPLACE, and UPDATE (From Mysql version 5.7 onwards) statements. Just like you, MySQL will have amazing plans for each query on how to execute, which index to pick, how to join tables and which order it should maintain for optimal performance. @@ -46,11 +48,14 @@ Table description **Let’s take a sample query and analyse what EXPLAIN yields to it.** +``` select * from master_users where email="akhil@gmail.com" +``` Explaining the above query gives as… Before Index + Let’s breakdown the EXPLAIN result. As you can see MySQL had traversed through 152685 rows (See the column: rows) of the table to find a matching row and its equal to a full table scan because the table has 153728 rows in total. @@ -58,7 +63,10 @@ EXPLAIN result has two columns with names as possible keys and key. possible_key As of now, both are empty. An empty key column provides you with the information that the query lacks an index. Let’s add one index and examine what happens. + +``` ALTER TABLE master_users ADD INDEX index_email(email) +``` After adding an index. @@ -68,15 +76,17 @@ If you notice, we have our index name present in both of the columns possible_ke **You optimized a simple query but mine is a complex one!!!** I know that the query optimized just now is a piece of cake for you. Before jumping into more complex queries, -I want you to learn the Rule of Thumb in indexing. +I want you to learn the **Rule of Thumb in indexing.** -MySQL can only use one index per each of the tables in a query (Exemptions are there. eg, Merging of indexes). -Which ideally means that a table in a query, must use a single index for all where-clause, table join, group-by and order-by. +*MySQL can only use one index per each of the tables in a query (Exemptions are there. eg, Merging of indexes). +Which ideally means that a table in a query, must use a single index for all where-clause, table join, group-by and order-by.* Believe me, learning this rule was a breakthrough in my career. I used to believe that, it’s required to add an individual single index on each of the columns used in WHERE clause, JOIN clause, group-by and order-by. Let’s take another query. +``` select * from master_users where email="akhil@gmail.com" and category_id=3 +``` Keeping the rule of thumb in mind, you already know that creating two indexes on email and category will not help. If separate single-column indexes exist on col1 and col2, MySQL optimizer attempts to use the Index Merge optimization or attempts to find the most restrictive index by deciding which index excludes more rows and using that index to fetch the rows. @@ -91,7 +101,9 @@ By adding several columns into an index you can narrow down the number of rows M Let’s see, how you can create a composite index. +``` ALTER TABLE ADD INDEX index_co1_col2(column1, column2, column3,...) +``` **Does the column’s order matters in a compound index?.** @@ -101,20 +113,26 @@ Order of precedence of other columns also dependent on the cardinality of respec Now, How will you find the cardinality or number of distinct values of a column?. You can just perform a distinctive count query on the column. (It’s advised not to perform such queries mentioned below in a production DB when it is running in the peak time of traffic.) +``` select count(distinct(email)) from master_users select count(distinct(category_id)) from master_users +``` Distinctive counts of each column Here you can see that the cardinality of the category_id column is less than that of email column so that we should create a composite index just as follows. +``` ALTER TABLE master_users ADD INDEX index_category_email(category_id, email) +``` As you observe the order in which these columns are indexed, and thus how they are sorted will restrict the usage of our index to some particular queries only. As an example, the index we’ve just created (category_id, email) would not be beneficial for a query such as: +``` select * from master_users where email=”akhil@gmail.com” +``` Why? Just now you said that a composite index will be beneficial for mine query. Well, there is a reason for it. @@ -130,49 +148,66 @@ There is another advantage for the composite index; If an index exists on (col1, if you have a three-column index on (col1, col2, col3), you have indexed search capabilities on (col1), (col1, col2), and (col1, col2, col3) For example, let’s take an index (status, category_id, email). This index will be useful in below queries. +``` select * from master_users where status=1 select * from master_users where status=1 and category_id=3 select * from master_users where status=1 and category_id=3 and email="akhil@gmail.com" +``` But not in the below queries; +``` select * from master_users where category_id=3 select * from master_users where category_id=3 and email="akhil@gmail.com" +``` **What if your query contains OR operator instead of AND?.** +``` select status,category_id from master_users where status=1 or category_id=3 +``` + In this case, MySQL won’t be able to use the index on queries having an OR condition, even if the query contains lookup column and maintains the order of WHERE clause same as the index. Therefore, it’s recommended to avoid such OR conditions and consider splitting the query to two parts, combined with a UNION DISTINCT (or even better, UNION ALL, in case you know there won’t be any duplicate results) +``` select status,category_id from master_users where status=1 UNION ALL select status,category_id from master_users where category_id=3 +``` **What if your query contains GROUP BY and ORDER BY** let’s take the same index (status, category_id, email), and you run the query: +``` select * from master_users where status=1 ORDER BY category_id +``` This will use the composite index for the WHERE clause and if you think this will narrow down the records with the status having value as 1, sadly you now need to perform a sort on these resulting records to get them sorted by category_id. This is because the index didn’t sort the results by category_id in any meaningful way and ORDER BY clause lacks the lookup column. This is known as a File Sort (some of you might have noticed this in an explain result). This happens because the index that we created failed to satisfy for the ORDER BY clause. -File Sort: A sort that occurs after the query; it requires fetching the data into a temporary buffer and sorting it before finally returning. This wouldn’t have been needed if the data was already sorted by the index in the way you wanted. +**File Sort**: A sort that occurs after the query; it requires fetching the data into a temporary buffer and sorting it before finally returning. This wouldn’t have been needed if the data was already sorted by the index in the way you wanted. This also applies even If you only wanted to read 10 rows. +``` select * from master_users where status=1 ORDER BY category_id limit 5 +``` You’ll still be fetching thousands of records, sorting them, and only after this, returning the top 5 while discarding the rest of the records you spent time processing. +``` select * from master_users where status=1 ORDER BY status, category_id +``` This query can leverage the usage of the mentioned index because it qualifies for both the WHERE clause and ORDER BY clause. Consider another query, which sorts rows by the status in ascending order, and then by the category_id in descending order. +``` select * from master_users where status=1 ORDER BY status ASC, category_id DESC +``` MySQL cannot use indexes when sorting with a mixed order (both ASC and DESC in the same ORDER BY clause). @@ -180,7 +215,9 @@ Note: This changed with the release of the reversed indexes functionality and My Whatever you saw against ORDER BY is also applicable to GROUP BY statements. if you run the following query with the composite index on (status, category_id, email): +``` select * from master_users where status=1 GROUP BY category_id +``` The records are already sorted by status, category_id and email. This allows you to quickly filter down all the records with status=1. After these results are returned they are also then sorted based on category_id since the index orders the rows differently than required in the query. @@ -221,7 +258,9 @@ MySQL can easily retrieve the Primary Key values for all the records with mode v Now, what if we add an index like this, +``` ALTER TABLE master_users ADD INDEX index_covering(mode, mobile) +``` Using above index, MySQL can easily retrieve the Primary Key values for all the records with mode value as 2, and to fetch the mobile column, MySQL no need to depend on the Primary Key index to fetch row data. Above query is completely covered by the index and hence known as a covering index. The ideal database design uses a covering index where practical; the query results are computed entirely from the index, without reading the actual table data. From b8b57f6fc052277e6db9f8cba17291793868a53b Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Sat, 10 Oct 2020 12:09:22 +0530 Subject: [PATCH 10/14] User tagging --- SQL/mysql_indexing_best_practices.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index 1ca7f4b..9a27005 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -1,5 +1,5 @@ --- -Author: Akhil Mathew +Author: Akhil Mathew @akhilmathew001 Title: MySQL indexing best practices. Description: Create indexes, but do it wisely. In this tutorial, I will explain the best practices that developers can implement From 7b66692c46873653b312474c4e155c395d121064 Mon Sep 17 00:00:00 2001 From: Akhil Date: Sat, 10 Oct 2020 12:45:17 +0530 Subject: [PATCH 11/14] Added reference images --- SQL/images/After-adding-index.png | Bin 0 -> 20066 bytes SQL/images/Index.png | Bin 0 -> 20157 bytes SQL/images/before_index.png | Bin 0 -> 20539 bytes SQL/images/distinctive-count.png | Bin 0 -> 23236 bytes SQL/images/table_description.png | Bin 0 -> 41498 bytes 5 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 SQL/images/After-adding-index.png create mode 100644 SQL/images/Index.png create mode 100644 SQL/images/before_index.png create mode 100644 SQL/images/distinctive-count.png create mode 100644 SQL/images/table_description.png diff --git a/SQL/images/After-adding-index.png b/SQL/images/After-adding-index.png new file mode 100644 index 0000000000000000000000000000000000000000..f2819dbc8f5371d4dcf6b78b16b5722d4cea6670 GIT binary patch literal 20066 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

)`T&QnjCoy;w3l0Bc^cku$Ei^# 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 geUO&x-yXPlsDct(VvU;a0ZYOAe07DSPHvj+t literal 0 HcmV?d00001 diff --git a/SQL/images/Index.png b/SQL/images/Index.png new file mode 100644 index 0000000000000000000000000000000000000000..5df4cfd886da67a840d05a5ad576272d5f6f13ca GIT binary patch literal 20157 zcmdqJRaj)pnxLIPK_P`(;qLD4?hb`-pl~bPrEr(R-QC^Y-QC^YeX{o6r~AzGIXyiW z|IL4s#Nx?}%!v3x@?Gzj!Sb?Vu+W&$00011LR?r80Qi&uEQdjY0v}~rHg17`!0ZGi zlp!G@SGMFfftMKeBH!$ltc~oQ^lS|Q##YvrhBS5twuXjQb|%*L7hoN{002HfLRdiA zIrVhSSPNMK3vfvW^>b3;lQ2JsNL3DQJ@QFf8~SM*fsb}H@?D)C2ddizssgt{>7t18 zC!Zj1Ke*`@KmOwv5c%2fU<^O0xj*pmVhtTLT#OtUYg#18Ez49uyvdjs#1TOSAqo5t zfDe13WoLljh2K{yVCCC?mxH8#pa%Y3{_a!4{^yhZ5D1aA`u=*MA41Y5CEVZT!B1*7 ze^)3>+884AcbTzE1^e%+qoMwvtIqvi=$e)`U*S-#T5`sJOq#sq?SU?PewzJ$LORL~ ztXCMRu0A9uS*B^&h+&DEG-c1LyhYTqk6_7KSlp7`{lT|;a|b463KcCq77`^!r?}q# zET~HP(}RN&6e= zeAw~jG6(3s|mU(Rl zf^|py2T=86vlMe>uxphs$zbWh3ev16+P5qX7-h`l005=T0M76qYkZf+OMB`nB})f( zd}&Vg^5B4E0lvtRh8W)8A;)#vzEOXbR&raKB3X0g)+6LQf;$Dp)uAu_G~=@ud5!|H z;p#DQ&>IVrc~?La8E$r7GO8Nl?4M%xVJ>9Nbdvbl9Hs8o0Dp6x^@!o%+@4qdsa}fyZ%y6ZBY> zcVTi6p+gb3ZdK;C3)d%CpKwwDHWU�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 A)&Kwi literal 0 HcmV?d00001 diff --git a/SQL/images/before_index.png b/SQL/images/before_index.png new file mode 100644 index 0000000000000000000000000000000000000000..adeb82a7f469aded380634df1e27b8a4c9037a8a GIT binary patch literal 20539 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 literal 0 HcmV?d00001 diff --git a/SQL/images/distinctive-count.png b/SQL/images/distinctive-count.png new file mode 100644 index 0000000000000000000000000000000000000000..a7d6f9c05924b8ee9246d3859a6cadd66432e76c GIT binary patch literal 23236 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 CH|CK5 literal 0 HcmV?d00001 diff --git a/SQL/images/table_description.png b/SQL/images/table_description.png new file mode 100644 index 0000000000000000000000000000000000000000..b755decc6be9f0db431b3933e1ee58a0d0bc0af8 GIT binary patch literal 41498 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 literal 0 HcmV?d00001 From 68d00c139c8173e005751f36b968d08cf2c4d9f7 Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Sat, 10 Oct 2020 12:49:45 +0530 Subject: [PATCH 12/14] Added table description reference image --- SQL/mysql_indexing_best_practices.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index 9a27005..5bb1e11 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -44,7 +44,8 @@ Just like you, MySQL will have amazing plans for each query on how to execute, w Check out the below table description, I want you to memorise this table as it will be using in most of my examples. The table doesn’t have any index at present. -Table description + +[Table description](/SQL/images/table_description.png) **Let’s take a sample query and analyse what EXPLAIN yields to it.** From 9f1b22ab3de5976ddae8c6c1d6a93056c46c37fa Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Sat, 10 Oct 2020 12:54:06 +0530 Subject: [PATCH 13/14] Added all the reference images --- SQL/mysql_indexing_best_practices.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/SQL/mysql_indexing_best_practices.md b/SQL/mysql_indexing_best_practices.md index 5bb1e11..d2eb26d 100644 --- a/SQL/mysql_indexing_best_practices.md +++ b/SQL/mysql_indexing_best_practices.md @@ -55,7 +55,7 @@ select * from master_users where email="akhil@gmail.com" Explaining the above query gives as… -Before Index +[Before Index](/SQL/images/before_index.png) Let’s breakdown the EXPLAIN result. @@ -69,7 +69,7 @@ Let’s add one index and examine what happens. ALTER TABLE master_users ADD INDEX index_email(email) ``` -After adding an index. +[After adding an index.](/SQL/images/After-adding-index.png) Now you can see that the query is better optimized and MySQL was able to find a matching result without traversing many rows. If you notice, we have our index name present in both of the columns possible_keys and key. @@ -119,7 +119,7 @@ select count(distinct(email)) from master_users select count(distinct(category_id)) from master_users ``` -Distinctive counts of each column +[Distinctive counts of each column](/SQL/images/distinctive-count.png) Here you can see that the cardinality of the category_id column is less than that of email column so that we should create a composite index just as follows. From b956859d4db7a4006a412f8cdf4de9f0d8262696 Mon Sep 17 00:00:00 2001 From: Akhil Mathew Date: Sat, 10 Oct 2020 12:56:09 +0530 Subject: [PATCH 14/14] Deleted redundent reference image --- SQL/images/Index.png | Bin 20157 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 SQL/images/Index.png diff --git a/SQL/images/Index.png b/SQL/images/Index.png deleted file mode 100644 index 5df4cfd886da67a840d05a5ad576272d5f6f13ca..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 20157 zcmdqJRaj)pnxLIPK_P`(;qLD4?hb`-pl~bPrEr(R-QC^Y-QC^YeX{o6r~AzGIXyiW z|IL4s#Nx?}%!v3x@?Gzj!Sb?Vu+W&$00011LR?r80Qi&uEQdjY0v}~rHg17`!0ZGi zlp!G@SGMFfftMKeBH!$ltc~oQ^lS|Q##YvrhBS5twuXjQb|%*L7hoN{002HfLRdiA zIrVhSSPNMK3vfvW^>b3;lQ2JsNL3DQJ@QFf8~SM*fsb}H@?D)C2ddizssgt{>7t18 zC!Zj1Ke*`@KmOwv5c%2fU<^O0xj*pmVhtTLT#OtUYg#18Ez49uyvdjs#1TOSAqo5t zfDe13WoLljh2K{yVCCC?mxH8#pa%Y3{_a!4{^yhZ5D1aA`u=*MA41Y5CEVZT!B1*7 ze^)3>+884AcbTzE1^e%+qoMwvtIqvi=$e)`U*S-#T5`sJOq#sq?SU?PewzJ$LORL~ ztXCMRu0A9uS*B^&h+&DEG-c1LyhYTqk6_7KSlp7`{lT|;a|b463KcCq77`^!r?}q# zET~HP(}RN&6e= zeAw~jG6(3s|mU(Rl zf^|py2T=86vlMe>uxphs$zbWh3ev16+P5qX7-h`l005=T0M76qYkZf+OMB`nB})f( zd}&Vg^5B4E0lvtRh8W)8A;)#vzEOXbR&raKB3X0g)+6LQf;$Dp)uAu_G~=@ud5!|H z;p#DQ&>IVrc~?La8E$r7GO8Nl?4M%xVJ>9Nbdvbl9Hs8o0Dp6x^@!o%+@4qdsa}fyZ%y6ZBY> zcVTi6p+gb3ZdK;C3)d%CpKwwDHWU�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 A)&Kwi