개요
쿼리 실행 절차
구분 | 단계 | 실행 주체 | 결과물 |
---|
1 | SQL 파싱 | SQL 파서(MariaDB 엔진) | SQL 파스 트리 |
2 | 최적화 및 실행 계획 수립 | 옵티마이저(MariaDB 엔진) | 실행 계획 |
3 | SQL 실행 | 스토리지 엔진 + MariaDB 엔진 | 쿼리 결과값 |
옵티마이저의 종류
규칙 기반 최적화 (RBO:Rule-based optimizer) | 옵티마이저에 내장된 우선순위에 따라 실행 계획을 수립 |
비용 기반 최적화 (CBO:Cost-based optimizer) | 부하 정보와 통계 정보를 이용해 각 실행 계획별 비용을 산출하여 최소 비용의 실행 계획을 선택 |
MariaDB 10.0의 통계 정보
- MariaDB 10.0부터 통합 통계 정보 관리 기능을 제공
- 인덱스 컬럼 외 컬럼의 통계 정보 관리 가능
- 통계 정보를 영구적으로 사용 가능: 통계 정보를 별도로 백업해 복구해서 사용할 수 있음
- 관리자가 직접 통계 정보 변경 가능
통합 통계 테이블
table_stat | 컬럼 | 의미 |
---|
| db_name | 대상 테이블이 속한 데이터베이스 명 |
| table_name | 대상 테이블의 이름 |
| cardianlity | 테이블의 레코드 건수 |
column_stat | 컬럼 | 의미 |
---|
| db_name | 대상 테이블이 속한 데이터베이스 명 |
| table_name | 대상 테이블의 이름 |
| column_name | 대상 컬럼 이름 |
| min_value | 해당 컬럼의 최소값(정수 타입도 문자열 포맷으로 저장) |
| max_value | 해당 컬럼의 최대값(정수 타입도 문자열 포맷으로 저장) |
| nulls_ratio | NULL 값의 비율(0:NULL 없음, 0.5:NULL값을 가진 레코드가 50%, 1: 모든 레코드가 NULL) |
| avg_length | 컬럼 값의 평균 바이트 수 |
| avg_frequency | 중복된 값을 가진 평균 레코드의 수(1:중복된 값 없음) |
index_stat | 컬럼 | 의미 |
---|
| db_name | 대상 테이블이 속한 데이터베이스 명 |
| table_name | 대상 테이블의 이름 |
| index_name | 대상 인덱스의 이름 |
| prefix_arity | 인덱스 컬럼 순번 |
| avg_frequency | 중복된 값을 가진 평균 레코드의 수(1:중복된 값 없음) |
통계 파라미터
파라미터 | 값 | 내용 |
---|
use_stat_tables | never | MySQL 5.6의 통계 정보 관리 방식과 동일, 통합 통계 테이블에는 통계를 수집하지 않음 |
use_stat_tables | complementary | 각 스토리지 엔진이 제공하는 통계정보를 우선적으로 사용하되 스토리지 엔진이 제공하는 정보가 부족하거나 없는 경우에는 MariaDB의 통합 정보가 사용됨 |
use_stat_tables | preferably | 각 스토리지 엔진별로 관리되는 통계 정보보다 MariaDB의 통합 통계 정보를 우선해서 사용 |
create table tabl_recalc as select * from employees;
insert into tabl_recalc select * from employees;
MariaDB [(none)]> show global variables like 'innodb_stats_auto_recalc';
+--------------------------+-------+
| Variable_name | Value |
+--------------------------+-------+
| innodb_stats_auto_recalc | ON |
+--------------------------+-------+
1 row in set (0.00 sec)
MariaDB [employees]> select * from mysql.table_stats where table_name='tabl_recalc';
Empty set (0.00 sec)
MariaDB [employees]> select * from mysql.innodb_table_stats where table_name='tabl_recalc';
+---------------+-------------+---------------------+--------+----------------------+--------------------------+
| database_name | table_name | last_update | n_rows | clustered_index_size | sum_of_other_index_sizes |
+---------------+-------------+---------------------+--------+----------------------+--------------------------+
| employees | tabl_recalc | 2017-04-14 21:33:55 | 299439 | 1057 | 0 |
+---------------+-------------+---------------------+--------+----------------------+--------------------------+
1 row in set (0.00 sec)
MariaDB [employees]> show global variables like 'use_stat_tables';
+-----------------+-------+
| Variable_name | Value |
+-----------------+-------+
| use_stat_tables | NEVER |
+-----------------+-------+
1 row in set (0.00 sec)
MariaDB [employees]> analyze table tabl_recalc;
+-----------------------+---------+----------+----------+
| Table | Op | Msg_type | Msg_text |
+-----------------------+---------+----------+----------+
| employees.tabl_recalc | analyze | status | OK |
+-----------------------+---------+----------+----------+
1 row in set (0.01 sec)
MariaDB [employees]> select * from mysql.table_stats where table_name='tabl_recalc';
Empty set (0.00 sec)
MariaDB [employees]> SET SESSION use_stat_tables='COMPLEMENTARY';
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> analyze table tabl_recalc;
+-----------------------+---------+----------+-----------------------------------------+
| Table | Op | Msg_type | Msg_text |
+-----------------------+---------+----------+-----------------------------------------+
| employees.tabl_recalc | analyze | status | Engine-independent statistics collected |
| employees.tabl_recalc | analyze | status | OK |
+-----------------------+---------+----------+-----------------------------------------+
2 rows in set (0.54 sec)
MariaDB [employees]> select * from mysql.table_stats where table_name='tabl_recalc';
+-----------+-------------+-------------+
| db_name | table_name | cardinality |
+-----------+-------------+-------------+
| employees | tabl_recalc | 300024 |
+-----------+-------------+-------------+
1 row in set (0.00 sec)
통계 수집 시 주의 사항
ANALYZE TABLE 명령이 실행되면 테이블을 풀 스캔하거나 인덱스 풀 스캔하여 통계 수집
마스터와 슬레이브 구조라면 슬레이브에서 통계 정보를 수집하여 마스터에 복사
통계 생성 구문
tbl 테이블, col1과 col2 컬럼, idx1과 idx2 인덱스에 대해서만 통계 정보 수집 |
---|
analyze table tbl persistent for columns (col1, col2) indexes (idx1, idx2); |
tbl 테이블, col1과 col2 컬럼에 대해서만 통계 수집 |
---|
analyze table tbl persistent for columns (col1, col2) indexes (); |
tbl 테이블, idx1, idx2 인덱스에 대해서만 통계 수집 |
---|
analyze table tbl persistent for columns () indexes (idx1, idx2); |
tbl 테이블에 대해서만 통계 수집 |
---|
analyze table tbl persistent for columns () indexes (); |
테이블, 모든 컬럼, 모든 인덱스의 통계 수집(=analyze table tbl; ) |
---|
analyze table tbl persistent for all; |
히스토그램 통계 정보
- 히스토그램: 컬럼 값의 분포도를 분석할 수 있는 통계 정보
- Height-Balanced Histogram 알고리즘 사용
MariaDB [employees]> desc mysql.column_stats;
+---------------+-----------------------------------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+-----------------------------------------+------+-----+---------+-------+
| db_name | varchar(64) | NO | PRI | NULL | |
| table_name | varchar(64) | NO | PRI | NULL | |
| column_name | varchar(64) | NO | PRI | NULL | |
| min_value | varbinary(255) | YES | | NULL | |
| max_value | varbinary(255) | YES | | NULL | |
| nulls_ratio | decimal(12,4) | YES | | NULL | |
| avg_length | decimal(12,4) | YES | | NULL | |
| avg_frequency | decimal(12,4) | YES | | NULL | |
| hist_size | tinyint(3) unsigned | YES | | NULL | |
| hist_type | enum('SINGLE_PREC_HB','DOUBLE_PREC_HB') | YES | | NULL | |
| histogram | varbinary(255) | YES | | NULL | |
+---------------+-----------------------------------------+------+-----+---------+-------+
11 rows in set (0.00 sec)
--MariaDB에서 히스토그램 사용
MariaDB [employees]> set histogram_size=20;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> set use_stat_tables='preferably';
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> set histogram_type='double_prec_hb';
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> analyze table salaries;
+--------------------+---------+----------+-----------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------------------+---------+----------+-----------------------------------------+
| employees.salaries | analyze | status | Engine-independent statistics collected |
| employees.salaries | analyze | status | OK |
+--------------------+---------+----------+-----------------------------------------+
2 rows in set (8.28 sec)
MariaDB [employees]> select table_name, min_value, max_value, hist_size, hist_type,
-> decode_histogram(hist_type, histogram) as histogram
-> from mysql.column_stats
-> where table_name='salaries' and column_name='salary'\G
*************************** 1. row ***************************
table_name: salaries
min_value: 38623
max_value: 158220
hist_size: 20
hist_type: DOUBLE_PREC_HB
histogram: 0.04030,0.03436,0.03273,0.03198,0.03232,0.03375,0.03688,0.04285,0.05443,0.07974,0.58065 <<< 버킷최대값 / (최대값-최소값) * 216 (single_prec_hb:28)
1 row in set (0.00 sec)
MariaDB [employees]> set histogram_size=100;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> set use_stat_tables='preferably';
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> set histogram_type='double_prec_hb';
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> analyze table salaries;
+--------------------+---------+----------+-----------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------------------+---------+----------+-----------------------------------------+
| employees.salaries | analyze | status | Engine-independent statistics collected |
| employees.salaries | analyze | status | OK |
+--------------------+---------+----------+-----------------------------------------+
2 rows in set (7.94 sec)
MariaDB [employees]> set optimizer_use_condition_selectivity=4;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> explain extended select * from salaries where to_date <= '1989-03-01';
+------+-------------+----------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+------+-------------+----------+------+---------------+------+---------+------+---------+----------+-------------+
| 1 | SIMPLE | salaries | ALL | NULL | NULL | NULL | NULL | 2844047 | 5.88 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
MariaDB [employees]> select count(*), (2844047*0.0588) as expected_value from salaries where to_date <= '1989-03-01';
+----------+----------------+
| count(*) | expected_value |
+----------+----------------+
| 125536 | 167229.9636 |
+----------+----------------+
1 row in set (2.40 sec)
MariaDB [employees]> set histogram_size=200;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> analyze table salaries;
+--------------------+---------+----------+-----------------------------------------+
| Table | Op | Msg_type | Msg_text |
+--------------------+---------+----------+-----------------------------------------+
| employees.salaries | analyze | status | Engine-independent statistics collected |
| employees.salaries | analyze | status | OK |
+--------------------+---------+----------+-----------------------------------------+
2 rows in set (9.70 sec)
MariaDB [employees]> explain extended
-> select * from salaries where to_date <= '1989-03-01';
+------+-------------+----------+------+---------------+------+---------+------+---------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+------+-------------+----------+------+---------------+------+---------+------+---------+----------+-------------+
| 1 | SIMPLE | salaries | ALL | NULL | NULL | NULL | NULL | 2844047 | 4.95 | Using where |
+------+-------------+----------+------+---------------+------+---------+------+---------+----------+-------------+
1 row in set, 1 warning (0.00 sec)
MariaDB [employees]> select count(*), (2844047*0.0495) as expected_value from salaries where to_date <= '1989-03-01';
+----------+----------------+
| count(*) | expected_value |
+----------+----------------+
| 125536 | 140780.3265 |
+----------+----------------+
1 row in set (2.83 sec)
조인 옵티마이저 옵션
- Exhaustive 검색: from절에 명시된 모든 테이블 조합에 대해서 실행 계획의 비용을 계산하여 최적의 조합 선택
- Heuristic 검색(Greedy 검색)
구분 | 내용 |
---|
1 | 전체 N개의 테이블 중에서 optimizer_search_depth 시스템 설정 변수에 정의된 개수의 테이블로 가능한 조인 조합을 생성 |
2 | 1번에서 생성된 조인 조합 중에서 최소 비용의 실행 계획 하나를 선정 |
3 | 2번에서 선정된 실행 계획의 첫 번째 테이블을 "부분 실행 계획"의 첫번째 테이블로 선정 |
4 | 전체 N-1개의 테이블 중에서(3번에서 선택된 테이블 제외) optimizer_search_depth 시스템 변수에 정의된 개수의 테이블로 가능한 조인 조합을 생성 |
5 | 4번에서 생성된 조인 조합들을 하나씩 3번에서 생성된 "부분 실행 계획"에 대입해서 실행 비용을 계산 |
6 | 5번의 비용 계산 결과, 가장 비용이 낮은 실행 계획을 골라서 그 중 두 번째 테이블을 3번에서 생성된 "부분 실행 계획"의 두 번째 테이블로 선정 |
7 | 남은 테이블이 모두 없어질 때까지 4~6번까지의 과정을 반복 실행하면서 "부분 실행 계획"에 테이블의 조인 순서를 기록 |
8 | 최종적으로 "부분 실행 계획"이 테이블의 조인 순서로 결정 |
- optimizer_search_depth의 default 값: 64
MariaDB [employees]> set session optimizer_prune_level=1;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> set session optimizer_search_depth=5;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> select * from tab01,tab02,tab03,tab04,tab05,tab06,tab07,tab08,tab09,tab10, tab11,tab12,tab13,tab14,tab15,tab16,tab17,tab18,tab19,tab20, tab21,tab22,tab23,tab24,tab25,tab26,tab27,tab28,tab29,tab30 where tab01.fd1=tab02.fd1 and tab02.fd1=tab03.fd2 and tab03.fd1=tab04.fd1 and tab04.fd2=tab05.fd2 and tab05.fd2=tab06.fd1 and tab06.fd2=tab07.fd2 and tab07.fd1=tab08.fd1 and tab08.fd1=tab09.fd2 and tab09.fd1=tab10.fd1 and tab10.fd2=tab11.fd2 and tab11.fd2=tab12.fd1 and tab12.fd2=tab13.fd2 and tab13.fd1=tab14.fd1 and tab14.fd1=tab15.fd2 and tab15.fd1=tab16.fd1 and tab16.fd2=tab17.fd2 and tab17.fd2=tab18.fd1 and tab18.fd2=tab19.fd2 and tab19.fd1=tab20.fd1 and tab20.fd1=tab21.fd2 and tab21.fd1=tab22.fd1 and tab22.fd2=tab23.fd2 and tab23.fd2=tab24.fd1 and tab24.fd2=tab25.fd2 and tab25.fd1=tab26.fd1 and tab26.fd1=tab27.fd2 and tab27.fd1=tab28.fd1 and tab28.fd2=tab29.fd2 and tab29.fd2=tab30.fd1;
(((결과 생략)))
2000 rows in set (0.09 sec)
MariaDB [employees]> set session optimizer_search_depth=64;
Query OK, 0 rows affected, 2 warnings (0.00 sec)
MariaDB [employees]> reset query cache;
Query OK, 0 rows affected (0.00 sec)
MariaDB [employees]> select * from tab01,tab02,tab03,tab04,tab05,tab06,tab07,tab08,tab09,tab10, tab11,tab12,tab13,tab14,tab15,tab16,tab17,tab18,tab19,tab20, tab21,tab22,tab23,tab24,tab25,tab26,tab27,tab28,tab29,tab30 where tab01.fd1=tab02.fd1 and tab02.fd1=tab03.fd2 and tab03.fd1=tab04.fd1 and tab04.fd2=tab05.fd2 and tab05.fd2=tab06.fd1 and tab06.fd2=tab07.fd2 and tab07.fd1=tab08.fd1 and tab08.fd1=tab09.fd2 and tab09.fd1=tab10.fd1 and tab10.fd2=tab11.fd2 and tab11.fd2=tab12.fd1 and tab12.fd2=tab13.fd2 and tab13.fd1=tab14.fd1 and tab14.fd1=tab15.fd2 and tab15.fd1=tab16.fd1 and tab16.fd2=tab17.fd2 and tab17.fd2=tab18.fd1 and tab18.fd2=tab19.fd2 and tab19.fd1=tab20.fd1 and tab20.fd1=tab21.fd2 and tab21.fd1=tab22.fd1 and tab22.fd2=tab23.fd2 and tab23.fd2=tab24.fd1 and tab24.fd2=tab25.fd2 and tab25.fd1=tab26.fd1 and tab26.fd1=tab27.fd2 and tab27.fd1=tab28.fd1 and tab28.fd2=tab29.fd2 and tab29.fd2=tab30.fd1;
(((결과 생략)))
2000 rows in set (0.10 sec)
실행 계획 분석
MariaDB [employees]> explain
-> select e.emp_no, e.first_name, s.from_date, s.salary
-> from employees e, salaries s
-> where e.emp_no = s.emp_no
-> limit 10;
+------+-------------+-------+-------+---------------+--------------+---------+--------------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+-------+---------------+--------------+---------+--------------------+--------+-------------+
| 1 | SIMPLE | e | index | PRIMARY | ix_firstname | 16 | NULL | 299335 | Using index |
| 1 | SIMPLE | s | ref | PRIMARY | PRIMARY | 4 | employees.e.emp_no | 4 | |
+------+-------------+-------+-------+---------------+--------------+---------+--------------------+--------+-------------+
2 rows in set (0.00 sec)
- 레코드는 쿼리 문장에서 사용된 테이블의 개수만큼 출력(임시테이블 포함)
- 실행 순서는 위에서 아래로 순서대로 표시(union이나 상관 서브 쿼리와 같은 경우 순서대로 표시되지 않을 수 있음)
- id 컬럼의 값이 작을 수록 쿼리의 outer부분이거나 먼저 접근한 테이블, id 컬럼의 값이 클수록 쿼리의 inner부분 또는 나중에 접근한 테이블
id 컬럼
MariaDB [employees]> explain
-> select
-> ((select count(*) from employees) + (select count(*) from departments)) as total_count;
+------+-------------+-------------+-------+---------------+-------------+---------+------+--------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------------+-------+---------------+-------------+---------+------+--------+----------------+
| 1 | PRIMARY | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
| 3 | SUBQUERY | departments | index | NULL | PRIMARY | 4 | NULL | 9 | Using index |
| 2 | SUBQUERY | employees | index | NULL | ix_hiredate | 3 | NULL | 299335 | Using index |
+------+-------------+-------------+-------+---------------+-------------+---------+------+--------+----------------+
3 rows in set (0.00 sec)
select_type 컬럼
SIMPLE | union이나 서브 쿼리를 사용하지 않는 단순한 select 쿼리, 실행계획에서 SIMPLE은 하나만 존재하며 일반적으로 제일 바깥 select쿼리가 SIMPLE로 표시 |
PRIMARY | union이나 서브 쿼리를 가지는 select 쿼리의 실행 계획에서 가장 바깥쪽(outer)에 있는 단위 쿼리, 실행계획에서 하나만 존재하며 일반적으로 제일 바깥 select쿼리가 PRIMARY로 표시 |
UNION | union으로 결합하는 단위 select쿼리 가운데 첫 번째를 제외한 두 번째 이후 단위 select 쿼리 |
DEPENDENT UNION | union이나 union all로 결합된 단위 쿼리가 외부의 의해 영향을 받는 쿼리 |
UNION RESULT | union 결과 테이블을 의미, id 값이 부여되지 않음 |
SUBQUERY | from절 이외에서 사용되는 서브 쿼리만을 의미 |
DEPENDENT SUBQUERY | 서브 쿼리가 바깥쪽(outer) select 쿼리에서 정의된 컬럼을 사용하는 경우 |
DERIVED | 단위 select쿼리의 실행 결과를 메모리나 디스크에 임시 테이블을 생성하는 것을 의미, 서브 쿼리가 from절에 사용된 경우 |
UNCACHEABLE SUBQUERY | 서브 쿼리 결과를 내부적인 캐시 공간에 저장되지 못하는 경우 1. 사용자 변수가 서브 쿼리에 사용된 경우 2. not-deterministic 속성의 스토어드 루틴이 서브 쿼리 내에 사용된 경우 3. UUID()나 RAND()와 같이 결과값이 호출될 때마다 달라지는 함수가 서브 쿼리에 사용된 경우 |
UNCACHEABLE UNION | union 쿼리 결과가 내부적인 캐시 공간에 저장되지 못하는 경우 |
MATERIALIZED | 서브 쿼리의 내용을 임시 테이블로 구체화(materialization)하는 경우 |
INSERT | insert문의 실행계획 |
--UNION
MariaDB [employees]> explain
-> select tb.* from (
-> (select emp_no from employees e1 limit 10)
-> union all
-> (select emp_no from employees e2 limit 10)
-> union all
-> (select emp_no from employees e3 limit 10)
-> ) tb;
+------+-------------+------------+-------+---------------+-------------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+------------+-------+---------------+-------------+---------+------+--------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 30 | |
| 2 | DERIVED | e1 | index | NULL | ix_hiredate | 3 | NULL | 299335 | Using index |
| 3 | UNION | e2 | index | NULL | ix_hiredate | 3 | NULL | 299335 | Using index |
| 4 | UNION | e3 | index | NULL | ix_hiredate | 3 | NULL | 299335 | Using index |
+------+-------------+------------+-------+---------------+-------------+---------+------+--------+-------------+
4 rows in set (0.00 sec)
--DEPENDENT UNION & UNION RESULT
MariaDB [employees]> explain
-> select *
-> from employees e1
-> where e1.emp_no in (
-> select e2.emp_no from employees e2 where e2.first_name='Matt'
-> union
-> select e3.emp_no from employees e3 where e3.first_name='Matt'
-> );
+------+--------------------+------------+--------+----------------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+--------------------+------------+--------+----------------------+---------+---------+------+--------+-------------+
| 1 | PRIMARY | e1 | ALL | NULL | NULL | NULL | NULL | 299335 | Using where |
| 2 | DEPENDENT SUBQUERY | e2 | eq_ref | PRIMARY,ix_firstname | PRIMARY | 4 | func | 1 | Using where |
| 3 | DEPENDENT UNION | e3 | eq_ref | PRIMARY,ix_firstname | PRIMARY | 4 | func | 1 | Using where |
| NULL | UNION RESULT | <union2,3> | ALL | NULL | NULL | NULL | NULL | NULL | |
+------+--------------------+------------+--------+----------------------+---------+---------+------+--------+-------------+
4 rows in set (0.00 sec)
--DEPENDENT SUBQUERY
MariaDB [employees]> explain
-> select e.first_name,
-> (select count(*)
-> from dept_emp de, dept_manager dm
-> where dm.dept_no=de.dept_no and de.emp_no=e.emp_no) as cnt
-> from employees e
-> where e.first_name='Matt';
+------+--------------------+-------+------+---------------------------+-------------------+---------+----------------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+--------------------+-------+------+---------------------------+-------------------+---------+----------------------+------+--------------------------+
| 1 | PRIMARY | e | ref | ix_firstname | ix_firstname | 16 | const | 233 | Using where; Using index |
| 2 | DEPENDENT SUBQUERY | de | ref | PRIMARY,ix_empno_fromdate | ix_empno_fromdate | 4 | employees.e.emp_no | 1 | Using index |
| 2 | DEPENDENT SUBQUERY | dm | ref | PRIMARY | PRIMARY | 4 | employees.de.dept_no | 1 | Using index |
+------+--------------------+-------+------+---------------------------+-------------------+---------+----------------------+------+--------------------------+
3 rows in set (0.00 sec)
--DERIVED
MariaDB [employees]> explain
-> select *
-> from (select de.emp_no from dept_emp de group by de.emp_no) tb,
-> employees e
-> where e.emp_no=tb.emp_no;
+------+-------------+------------+--------+---------------+-------------------+---------+-----------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+------------+--------+---------------+-------------------+---------+-----------+--------+-------------+
| 1 | PRIMARY | <derived2> | ALL | NULL | NULL | NULL | NULL | 331570 | |
| 1 | PRIMARY | e | eq_ref | PRIMARY | PRIMARY | 4 | tb.emp_no | 1 | |
| 2 | DERIVED | de | index | NULL | ix_empno_fromdate | 7 | NULL | 331570 | Using index |
+------+-------------+------------+--------+---------------+-------------------+---------+-----------+--------+-------------+
3 rows in set (0.00 sec)
--UNCACHEABLE SUBQUERY
MariaDB [employees]> explain
-> select *
-> from employees e
-> where e.emp_no = (
-> select @status from dept_emp de where de.dept_no='d005'
-> );
+------+----------------------+-------+-------+---------------+---------+---------+-------+--------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+----------------------+-------+-------+---------------+---------+---------+-------+--------+--------------------------+
| 1 | PRIMARY | e | const | PRIMARY | PRIMARY | 4 | const | 1 | Using where |
| 2 | UNCACHEABLE SUBQUERY | de | ref | PRIMARY | PRIMARY | 4 | const | 165785 | Using where; Using index |
+------+----------------------+-------+-------+---------------+---------+---------+-------+--------+--------------------------+
2 rows in set (0.01 sec)
MariaDB [employees]> explain
-> select *
-> from employees e
-> where e.emp_no in (select emp_no from salaries where salary between 100 and 1000);
+------+--------------+-------------+--------+-------------------+-----------+---------+---------------------------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+--------------+-------------+--------+-------------------+-----------+---------+---------------------------+------+--------------------------+
| 1 | PRIMARY | <subquery2> | ALL | distinct_key | NULL | NULL | NULL | 1 | |
| 1 | PRIMARY | e | eq_ref | PRIMARY | PRIMARY | 4 | employees.salaries.emp_no | 1 | |
| 2 | MATERIALIZED | salaries | range | PRIMARY,ix_salary | ix_salary | 4 | NULL | 1 | Using where; Using index |
+------+--------------+-------------+--------+-------------------+-----------+---------+---------------------------+------+--------------------------+
3 rows in set (0.00 sec)
--INSERT
MariaDB [employees]> explain
-> insert into employees values (1, '2014-01-01', 'Matt', 'Lee', 'M', '2014-01-02');
+------+-------------+-----------+------+---------------+------+---------+------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+------+---------------+------+---------+------+------+-------+
| 1 | INSERT | employees | ALL | NULL | NULL | NULL | NULL | NULL | NULL |
+------+-------------+-----------+------+---------------+------+---------+------+------+-------+
1 row in set (0.00 sec)
MariaDB [employees]> explain
-> update employees set gender='F' where first_name='Matt';
+------+-------------+-----------+-------+---------------+--------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+-------+---------------+--------------+---------+------+------+-------------+
| 1 | SIMPLE | employees | range | ix_firstname | ix_firstname | 16 | NULL | 233 | Using where |
+------+-------------+-----------+-------+---------------+--------------+---------+------+------+-------------+
1 row in set (0.00 sec)
- table 컬럼
- 테이블 이름에 별칭이 있는 경우 실행 계획에서 별칭으로 표시
- 테이블이 없거나 dual 테이블 사용 시 NULL로 표시
MariaDB [employees]> explain select now();
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
MariaDB [employees]> explain select now() from dual;
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
type 컬럼
- 각 테이블의 레코드를 어떤 방식으로 읽었는지를 나타냄
system | 레코드가 1건만 존재하는 테이블 또는 한 건도 존재하는 않는 테이블을 참조하는 형태의 접근 방법, InnoDB, XtraDB 스토리지 엔진에서는 안나오고 MyISAM, MEMORY 테이블에서만 사용 |
const | 테이블의 레코드의 건수에 관계없이 쿼리가 프라이머리 키나 유니크 키 컬럼을 이용하는 where 조건절을 가지고 있으며, 반드시 1건을 반환하는 쿼리의 처리 방식 |
eq_ref | 조인에서 처음 읽은 테이블의 컬럼 값을 그 다음 읽어야 할 테이블의 프라이머리 키나 유니크 키 컬럼의 검색 조건에 사용할 때 |
ref | 조인의 순서와 인덱스의 종류에 관계없이 동등 조건으로 검색 |
fulltext | MariaDB의 전문 검색 인덱스를 사용해 레코드를 읽는 접근 방법을 의미 |
ref_or_null | ref 방식 또는 NULL 비교 접근 방식 |
unique_subquery | where 조건절에서 사용될 수 있는 IN(sebquery)형태의 쿼리를 위한 접근 방식 |
index_subquery | IN(subquery)형태의 조건에서 subquery의 반환 값에 중복된 값이 있을 수 있지만 인덱스를 이용해 중복된 값을 제거 |
range | 인덱스 레인지 스캔 형태의 접근 방법 |
index_merge | 2개 이상의 인덱스를 이용해 각각의 검색 결과를 만들어낸 후 그 결과를 병합하는 처리 방식 |
index | 인덱스 풀 스캔 |
ALL | 테이블 풀 스캔 |
-- const
MariaDB [employees]> explain select * from employees where emp_no=10001;
+------+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
| 1 | SIMPLE | employees | const | PRIMARY | PRIMARY | 4 | const | 1 | |
+------+-------------+-----------+-------+---------------+---------+---------+-------+------+-------+
1 row in set (0.00 sec)
--eq_ref
MariaDB [employees]> explain
-> select * from dept_emp de, employees e
-> where e.emp_no=de.emp_no and de.dept_no='d005';
+------+-------------+-------+--------+---------------------------+---------+---------+---------------------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+---------------------------+---------+---------+---------------------+--------+-------------+
| 1 | SIMPLE | de | ref | PRIMARY,ix_empno_fromdate | PRIMARY | 4 | const | 165785 | Using where |
| 1 | SIMPLE | e | eq_ref | PRIMARY | PRIMARY | 4 | employees.de.emp_no | 1 | |
+------+-------------+-------+--------+---------------------------+---------+---------+---------------------+--------+-------------+
2 rows in set (0.00 sec)
--ref
MariaDB [employees]> explain
-> select * from dept_emp where dept_no='d005';
+------+-------------+----------+------+---------------+---------+---------+-------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+---------+---------+-------+--------+-------------+
| 1 | SIMPLE | dept_emp | ref | PRIMARY | PRIMARY | 4 | const | 165785 | Using where |
+------+-------------+----------+------+---------------+---------+---------+-------+--------+-------------+
1 row in set (0.00 sec)
--fulltext
MariaDB [employees]> explain
-> select *
-> from employee_name
-> where match(first_name, last_name) against ('Facello' in boolean mode);
+------+-------------+---------------+----------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+---------------+----------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | employee_name | fulltext | fx_name | fx_name | 0 | | 1 | Using where |
+------+-------------+---------------+----------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)
--ref_or_null
MariaDB [employees]> explain
-> select *
-> from titles where to_date='1985-03-01' or to_date is null;
+------+-------------+--------+-------------+---------------+-----------+---------+-------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+--------+-------------+---------------+-----------+---------+-------+------+--------------------------+
| 1 | SIMPLE | titles | ref_or_null | ix_todate | ix_todate | 4 | const | 2 | Using where; Using index |
+------+-------------+--------+-------------+---------------+-----------+---------+-------+------+--------------------------+
1 row in set (0.01 sec)
--range
MariaDB [employees]> explain
-> select * from employees where emp_no between 10002 and 10004;
+------+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
| 1 | SIMPLE | employees | range | PRIMARY | PRIMARY | 4 | NULL | 3 | Using where |
+------+-------------+-----------+-------+---------------+---------+---------+------+------+-------------+
1 row in set (0.00 sec)
--index_merge
MariaDB [employees]> explain
-> select *
-> from employees
-> where emp_no between 10001 and 11000
-> or first_name='Smith';
+------+-------------+-----------+-------------+----------------------+----------------------+---------+------+------+------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-----------+-------------+----------------------+----------------------+---------+------+------+------------------------------------------------+
| 1 | SIMPLE | employees | index_merge | PRIMARY,ix_firstname | PRIMARY,ix_firstname | 4,16 | NULL | 1000 | Using union(PRIMARY,ix_firstname); Using where |
+------+-------------+-----------+-------------+----------------------+----------------------+---------+------+------+------------------------------------------------+
1 row in set (0.00 sec)
--index
MariaDB [employees]> explain
-> select *
-> from departments
-> order by dept_name desc limit 10;
+------+-------------+-------------+-------+---------------+-------------+---------+------+------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------------+-------+---------------+-------------+---------+------+------+-------------+
| 1 | SIMPLE | departments | index | NULL | ux_deptname | 42 | NULL | 9 | Using index |
+------+-------------+-------------+-------+---------------+-------------+---------+------+------+-------------+
1 row in set (0.00 sec)
possibel_keys 컬럼
- 옵티마이저가 최적의 실행 계획을 만들기 위해 후보로 선정했던 접근 방식에서 사용되는 인덱스 목록
- "사용될 법했던 인덱스의 목록"으로 실제 그 인덱스를 사용하지는 않을 수 있음
key 컬럼
- 최종 선택된 실행 계획에서 사용하는 인덱스를 의미
- PRIMARY인 경우에는 프라이머리 키를 사용한다는 의미, 그 의외의 값은 테이블이나 인덱스를 생성할 때 부여했던 고유 이름
key_len 컬럼
- 쿼리를 처리하기 위해 다중 컬럼으로 구성된 인덱스에서 몇 개의 컬럼까지 사용했는지 표시
- 인덱스의 각 레코드에서 몇 바이트까지 사용했는지 알려주는 값
MariaDB [employees]> explain
-> select * from dept_emp where dept_no='d005';
+------+-------------+----------+------+---------------+---------+---------+-------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+------+---------------+---------+---------+-------+--------+-------------+
| 1 | SIMPLE | dept_emp | ref | PRIMARY | PRIMARY | 4 | const | 165785 | Using where |
+------+-------------+----------+------+---------------+---------+---------+-------+--------+-------------+
1 row in set (0.00 sec)
MariaDB [employees]> explain
-> select * from dept_emp where dept_no='d005' and emp_no=10001;
+------+-------------+----------+-------+---------------------------+---------+---------+-------------+------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+----------+-------+---------------------------+---------+---------+-------------+------+-------+
| 1 | SIMPLE | dept_emp | const | PRIMARY,ix_empno_fromdate | PRIMARY | 8 | const,const | 1 | |
+------+-------------+----------+-------+---------------------------+---------+---------+-------------+------+-------+
1 row in set (0.00 sec)
MariaDB [employees]> explain
-> select * from titles where to_date <= '1985-10-10';
+------+-------------+--------+-------+---------------+-----------+---------+------+------+--------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+--------+-------+---------------+-----------+---------+------+------+--------------------------+
| 1 | SIMPLE | titles | range | ix_todate | ix_todate | 4 | NULL | 51 | Using where; Using index |
+------+-------------+--------+-------+---------------+-----------+---------+------+------+--------------------------+
1 row in set (0.00 sec)
-- to_date is nullable: date 3byte + null 1byte
ref 컬럼
- 참조 조건(equal 비교 조건)으로 어떤 값이 제공됐는지 표시
- 상수 값을 지정했다면 const로 표시, 다른 테이블의 컬럼이면 그 테이블 명과 컬럼 명이 표시
MariaDB [employees]> explain
-> select * from employees e, dept_emp de
-> where e.emp_no=de.emp_no;
+------+-------------+-------+--------+-------------------+---------+---------+---------------------+--------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+-------------------+---------+---------+---------------------+--------+-------+
| 1 | SIMPLE | de | ALL | ix_empno_fromdate | NULL | NULL | NULL | 331570 | |
| 1 | SIMPLE | e | eq_ref | PRIMARY | PRIMARY | 4 | employees.de.emp_no | 1 | |
+------+-------------+-------+--------+-------------------+---------+---------+---------------------+--------+-------+
2 rows in set (0.00 sec)
MariaDB [employees]> explain
-> select * from employees e, dept_emp de
-> where e.emp_no=(de.emp_no-1);
+------+-------------+-------+--------+---------------+---------+---------+------+--------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+---------------+---------+---------+------+--------+-------------+
| 1 | SIMPLE | de | ALL | NULL | NULL | NULL | NULL | 331570 | |
| 1 | SIMPLE | e | eq_ref | PRIMARY | PRIMARY | 4 | func | 1 | Using where |
+------+-------------+-------+--------+---------------+---------+---------+------+--------+-------------+
2 rows in set (0.00 sec)
rows 컬럼
- 실행 계획의 효율성 판단을 위해 예측했던 레코드 건수를 표시
constrow not found | 쿼리의 실행계획에서 const 접근 방식으로 테이블을 읽었지만 실제로 해당 테이블에 레코드가 1건도 존재하지 않는 경우 |
Distinct | 중복 제거 표시 |
Full scan on NUll key | col1 IN (select col2 from ...) 쿼리에서 col1이 값이 NULL이면 풀 테이블 스캔을 사용할 것을 표시 |
Impossible HAVING | 쿼리에 사용된 having절의 조건을 만족하는 레코드가 없을 때 표시, 쿼리가 제대로 작성되지 못한 경우가 대부분으로 쿼리를 다시 점검 |
Impossible WHERE | where 조건이 항상 false가 될 수밖에 없는 경우 |
Impossible WHERE noticed after reading const tables | 실행 계획을 만드는 과정에서 쿼리의 일부분을 실행해 본 후 where 조건이 false인 경우 |
No matching min/max row | min(), max()와 같은 집합 함수가 있는 쿼리의 조건절에 일치하는 레코드가 한 건도 없을 때 표시 |
No matching row in const table | 조인에 사용된 테이블에서 const방식으로 접근할 때 일치하는 레코드가 없는 것을 표시 |
No tables used | from절이 없는 쿼리 문장이나 "from dual"을 표시 |
Not exists | outer조인을 이용해 안티-조인을 수행하는 쿼리 표시 |
Range checked for each record(index map: N) | 조인 조건이 모두 변수인 경우 매 레코드마다 인덱스 레인지 스캔을 표시 |
--Distinct
MariaDB [employees]> explain
-> select distinct d.dept_no
-> from departments d, dept_emp de where de.dept_no=d.dept_no;
+------+-------------+-------+-------+---------------+---------+---------+---------------------+-------+------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+-------+---------------+---------+---------+---------------------+-------+------------------------------+
| 1 | SIMPLE | d | index | PRIMARY | PRIMARY | 4 | NULL | 9 | Using index; Using temporary |
| 1 | SIMPLE | de | ref | PRIMARY | PRIMARY | 4 | employees.d.dept_no | 20723 | Using index; Distinct |
+------+-------------+-------+-------+---------------+---------+---------+---------------------+-------+------------------------------+
2 rows in set (0.00 sec)
--Full scan on NULL key
MariaDB [employees]> explain
-> select d.dept_no, null in (select id.dept_name from departments id)
-> from departments d;
+------+-------------+-------+----------------+---------------+-------------+---------+-------+------+-------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+----------------+---------------+-------------+---------+-------+------+-------------------------------------------------+
| 1 | PRIMARY | d | index | NULL | PRIMARY | 4 | NULL | 9 | Using index |
| 2 | SUBQUERY | id | index_subquery | ux_deptname | ux_deptname | 42 | const | 1 | Using index; Using where; Full scan on NULL key |
+------+-------------+-------+----------------+---------------+-------------+---------+-------+------+-------------------------------------------------+
2 rows in set (0.00 sec)
--Impossible HAVING
MariaDB [employees]> explain
-> select e.emp_no, count(*) as cnt
-> from employees e
-> where e.emp_no=10001
-> group by e.emp_no
-> having e.emp_no is null;
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible HAVING |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------+
1 row in set (0.00 sec)
--Impossible WHERE
MariaDB [employees]> explain
-> select * from employees where emp_no is null;
+------+-------------+-------+------+---------------+------+---------+------+------+------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE |
+------+-------------+-------+------+---------------+------+---------+------+------+------------------+
1 row in set (0.00 sec)
--Impossible WHERE noticed after reading const tables
MariaDB [employees]> explain
-> select * from employees where emp_no=0;
+------+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | Impossible WHERE noticed after reading const tables |
+------+-------------+-------+------+---------------+------+---------+------+------+-----------------------------------------------------+
1 row in set (0.00 sec)
--No matching min/max row
MariaDB [employees]> explain
-> select min(dept_no), max(dept_no)
-> from dept_emp where dept_no='';
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No matching min/max row |
+------+-------------+-------+------+---------------+------+---------+------+------+-------------------------+
1 row in set (0.00 sec)
--No tables used
MariaDB [employees]> explain select now();
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
MariaDB [employees]> explain select now() from dual;
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
| 1 | SIMPLE | NULL | NULL | NULL | NULL | NULL | NULL | NULL | No tables used |
+------+-------------+-------+------+---------------+------+---------+------+------+----------------+
1 row in set (0.00 sec)
--Not exists
MariaDB [employees]> explain
-> select *
-> from dept_emp de
-> left join departments d on de.dept_no=d.dept_no
-> where d.dept_no is null;
+------+-------------+-------+--------+---------------+---------+---------+----------------------+--------+-------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+--------+---------------+---------+---------+----------------------+--------+-------------------------+
| 1 | SIMPLE | de | ALL | NULL | NULL | NULL | NULL | 331570 | |
| 1 | SIMPLE | d | eq_ref | PRIMARY | PRIMARY | 4 | employees.de.dept_no | 1 | Using where; Not exists |
+------+-------------+-------+--------+---------------+---------+---------+----------------------+--------+-------------------------+
2 rows in set (0.00 sec)
--Range checked for each record
MariaDB [employees]> explain select * from employees e1, employees e2 where e2.emp_no >= e1.emp_no;
+------+-------------+-------+------+---------------+------+---------+------+--------+------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+------+-------------+-------+------+---------------+------+---------+------+--------+------------------------------------------------+
| 1 | SIMPLE | e1 | ALL | PRIMARY | NULL | NULL | NULL | 299335 | |
| 1 | SIMPLE | e2 | ALL | PRIMARY | NULL | NULL | NULL | 299335 | Range checked for each record (index map: 0x1) |
+------+-------------+-------+------+---------------+------+---------+------+--------+------------------------------------------------+
2 rows in set (0.00 sec)