In the use of the database, writing the correct SQL statement is only the first step in the long march. In fact, in the daily work of DBA, SQL optimization occupies a large part of the content, this article will introduce some basic knowledge about SQL optimization.
1. Basic concepts
Before understanding how to optimize SQL statements, we must first understand a few basic concepts
1.1 Execution plan
The execution plan is the execution mode of the SQL statement. The execution mode designed for the statement by the query optimizer is handed over to the executor for execution. Use EXPLAIN on the SQL command line to print out the execution plan of the statement.
1.2 Operator
Operators are the basic unit of SQL execution. All SQL statements are finally converted into a series of operators and finally executed on the server to get the required results.
Operators are also the basis for understanding the execution plan, here are the frequently occurring operators
CSCN SSCN SSEK CSEK BLKUP
These operators are the original source of SQL query data. The base tables appearing in SQL will appear in the description of these operators. These operators are used to determine when and how the corresponding table is entered in the execution plan. .
The specific meaning of the operators are listed below
CSCN: Basic full table scan (a), scan all from beginning to end
SSCN: secondary index scan (b), scan all from beginning to end
SSEK: Secondary index range scan (b), accurately locate the range or single value by key value
CSEK: Clustered index range scan (c), accurately locate the range or single value by key value
BLKUP: Retrieve all data from the original table based on the ROWID of the secondary index (b + a)
For more operator explanation, please refer to Appendix 4 "Execution Plan Operator" of DM7 System Administrator Manual
2. Build an experimental environment
Create table T1 and enter the data, the relevant SQL statements are as follows
SQL> CREATE TABLE T1(C1 INT,C2 INT);
SQL> insert into t1 select level,level from dualconnect by level < 10000;
3. Inspection execution plan
--SEL1
SQL> explain select * from t1 where c1 = 5;
1 #NSET2: [1, 249, 16]
2 #PRJT2: [1, 249, 16]; exp_num(3),is_atom(FALSE)
3 #SLCT2: [1, 249, 16]; T1.C1 =5
4 #CSCN2: [1, 9999, 16];INDEX33555446(T1)
We have created a normal table without any indexes, filtering, and taking out data from T1 can only go through the full table scan CSCN
Let's create an index
SQL> create index i_test1 on t1(c1);
Look at the plan of the following statement
--SEL2
SQL> explain select c1 from t1;
1 #NSET2: [1, 9999, 12]
2 #PRJT2: [1, 9999, 12]; exp_num(2),is_atom(FALSE)
3 #SSCN: [1, 9999, 12];I_TEST1(T1)
--SEL3
SQL> explain select c2 from t1;
1 #NSET2: [1, 9999, 12]
2 #PRJT2: [1, 9999, 12]; exp_num(2),is_atom(FALSE)
3 #CSCN2: [1, 9999, 12]; INDEX33555446(T1)
At this time, there are two entries in T1, CSCN T1 base table, or SSCN secondary index I_TEST1, SEL2, only C1 is required, C1 exists on the secondary index, and the data length is less than the basic table (one more C2), Index selection SSCN
For SEL3, there is still no better entry, or choose CSCN full table
##Generally speaking, we think that the time-consuming of CSCN and SSCN is almost the same. The difference between SSCN and CSCN is that the data scanned by SSCN is sorted by index column, which can be used in some cases
Now look at the situation of SSEK
--SEL4
SQL> explain select * from t1 where c1 = 5;
1 #NSET2: [0, 249, 16]
2 #PRJT2: [0, 249, 16]; exp_num(3),is_atom(FALSE)
3 #BLKUP2: [0, 249, 16];I_TEST1(T1)
4 #SSEK2: [0, 249, 16];scan_type(ASC), I_TEST1(T1), scan_range[5,5]
The query condition C1 = how many, there is a C1 index. It should be noted that the description after the operator scan_range[5,5] indicates that it is accurately positioned to 5. Undoubtedly, this is more efficient in most cases.
Another point, the BLKUP operator appears on SSEK, because there is no C2 data on I_TEST1, and the query requires SELECT *, the index requires BLKUP to return to the original table to find the entire row of data
Very easy, we can think that if only query C1, then the BLKUP operator should not exist, verify
--SEL5
SQL> explain select c1 from t1 where c1 = 5;
1 #NSET2: [0, 249, 12]
2 #PRJT2: [0, 249, 12]; exp_num(2),is_atom(FALSE)
3 #SSEK2: [0, 249, 12];scan_type(ASC), I_TEST1(T1), scan_range[5,5]
Indeed
The clustered index is a special index (corresponding to the operator CSEK). On DM7, only one clustered index of the same table is allowed. When the table is built by default (without a heap table), the base table is a ROWID Clustered index, it can be expected that the precise positioning of ROWID should go CSEK
--SEL6
SQL> explain select c1 from t1 where rowid = 6;
1 #NSET2: [0, 1, 12]
2 #PRJT2: [0, 1, 12]; exp_num(2),is_atom(FALSE)
3 #CSEK2: [0, 1, 12];scan_type(ASC), INDEX33555446(T1), scan_range[exp_cast(6),exp_cast(6)]
If we create a custom clustered index
SQL> create cluster index i_index2 on t1(c2);
Then the clustered index ROWID does not exist, instead it refers to the clustered index in the order of C2
--SEL7
SQL> explain select c1 from t1 where rowid = 6;
1 #NSET2: [1, 249, 12]
2 #PRJT2: [1, 249, 12]; exp_num(1),is_atom(FALSE)
3 #SLCT2: [1, 249, 12];T1.ROWID = var1
4 #SSCN: [1, 9999, 12];I_TEST1(T1)
##C1 and ROWID are required in the query, and the ordinary secondary index I_TEST1 happens to be there, and it is shorter than the length of the clustered index, so choose SSCN I_TEST1
--SEL8
SQL> explain select c1 from t1 where c2 = 6;
1 #NSET2: [0, 249, 8]
2 #PRJT2: [0, 249, 8]; exp_num(1),is_atom(FALSE)
3 #CSEK2: [0, 249, 8]; scan_type(ASC),I_INDEX2(T1), scan_range[6,6]
We can see that the precise positioning of ROWID no longer uses the precise positioning CSEK, but the full index scan I_TEST1, the precise filtering of C2 takes the CSEK, and there is no BLKUP