Lesson 21 of the SQL Optimization Course: Composite Indexes 2

For relational databases, the design of tables and SQL is written are particularly crucial. It wouldn’t be an exaggeration to say that they account for 90% of performance. So this time, specifically targeting these two major knowledge areas, we’ll conduct a detailed analysis for you, peeling back the layers.
This Series uses plain and understandable language and selects a large number of examples to elaborate on the subtleties for you.
🧑💻 Target audience:
We will use MySQL as the demonstration database.
The previous article delved into the concept of MySQL composite indexes and their applicable scenarios. This piece focuses on situations where composite indexes may not be suitable and offers corresponding optimization strategies.
Syntax of Composite Indexes (default ascending order):
|
|
Prerequisites: The column f1 must be present in the SQL statement’s filtering conditions!
In other words, the first column of a composite index (the leftmost column) must exist in the filtering conditions. Ideally, it should be used for equality filtering. Consider the following SQL statements, none of which are suitable for composite indexes.
|
|
Let’s analyze each SQL statement one by one:
The filtering condition only includes column f2, which is the second column in the composite index idx_multi. Since the index entry cannot be found through column f2, the index cannot be directly utilized. For such statements, a single-column index should be created on column f2.
|
|
Comparison of execution plans before and after adding the index:
Before adding idx_f2, a full table scan occurred with no available indexes.
|
|
After adding idx_f2, the index is directly used to filter records:
|
|
Similar to SQL 1, a single-column index can be created on column f3.
|
|
The filtering condition for SQL 3 involves columns (f2, f3) with equality filtering. However, it does not meet the essential characteristics of the composite index idx_multi as column f1 is not included in the filtering conditions. Previously, single-column indexes were created for columns f2 and f3. MySQL’s Index Merge feature can be leveraged to combine these two indexes and take their intersection. The execution plan is as follows:
|
|
It can be observed that MySQL utilized Index Merge to filter data. However, if such statements occur frequently, it is advisable to add a composite index that only includes columns f2 and f3.
|
|
The execution plan is as follows:
|
|
It can be seen that MySQL chose the index idx_multi_sub to filter data, and the type is ref, which is more optimized compared to index_merge.
The filtering condition for SQL 4 involves columns f2 and f3, but the relationship between them is OR instead of AND, and column f1 is not included. This does not align with the characteristics of a composite index.
For such statements, if the filtering performance of the given conditions for columns f2 and f3 is acceptable, single-column indexes can be created for both columns. MySQL can use index_merge to combine the two single-column indexes for filtering. The execution plan is as follows:
|
|
Some suggest that replacing OR with UNION ALL can avoid such operations. However, this depends on the context. For the above SQL statement, index_merge simply performs a union of indexes idx_f2 and idx_f3 without sorting. In this case, the performance difference between OR and UNION ALL is minimal. Further optimization of OR and UNION ALL will be covered in a separate article and will not be elaborated here.
These two SQL statements can utilize the composite index idx_multi because column f1 is included in the filtering conditions. However, since the other conditions are OR instead of AND, single-column indexes should also be created for the columns after OR. This way, MySQL can perform an index_merge between idx_multi and other single-column indexes to optimize the query. Let’s examine the execution plans for these two SQL statements:
|
|
It can be observed that MySQL utilized both idx_multi and idx_f2, as well as idx_multi and idx_f3. However, the index_merge in both execution plans used sort_union. Can sort_union be replaced with a regular non-sorting union? To achieve this, a single-column index should be added to column f1.
|
|
Let’s randomly check the execution plan for SQL 5:
|
|
After adding a single-column index to column f1, index_merge avoids sort_union.
Similar to the previous two SQL statements, SQL 7 requires the use of a single-column index on column f1. The difference is that index_merge involves three columns instead of two. The execution plan is as follows:
|
|
It can be clearly seen that MySQL utilized index_merge with three single-column indexes.
At this point, table t1 has numerous indexes:
|
|
From the above table structure, it can be seen that, in addition to the primary key, five secondary indexes have been created for these seven SQL statements. In practical scenarios, it is not necessary to create all these indexes. The decision should be based on the frequency of the SQL statements. If a particular SQL statement has a low execution frequency and its allowed execution time does not conflict with business peak hours, the corresponding index can be removed to reduce the latency caused by indexes on table writes.
👋 See you in the next lesson.
SQLFlash is your AI-powered SQL Optimization Partner.
Based on AI models, we accurately identify SQL performance bottlenecks and optimize query performance, freeing you from the cumbersome SQL tuning process so you can fully focus on developing and implementing business logic.
Join us and experience the power of SQLFlash today!.