クエリのパフォーマンスを決める実行計画を見てみよう
さて、
こうした理由からクエリの遅延が発生したとき、
- シーケンシャルアクセスの実行計画
- ランダムアクセスの実行計画
- 結合の実行計画
シーケンシャルアクセスの実行計画
実行計画を確認する手段は実装によって違いますが、
DBMS | 実行計画取得コマンド |
---|---|
Oracle | set autotrace traceonly |
SQL Server | SET SHOWPLAN_ |
DB2 | EXPLAIN ALL WITH SNAPSHOT FOR <SQL文> |
PostgreSQL | EXPLAIN <SQL文> |
MySQL | EXPLAIN EXTENDED <SQL文> |
※ OracleおよびSQL Serverでは、
具体的に、
Shops
: | |||
まずは、
SELECT *
FROM Shops;
Oracle、
実行計画
----------------------------------------------------------
Plan hash value: 2761254732
② ① ③
------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 60 | 1260 | 3 (0)| 00:00:01 |
| 1 | TABLE ACCESS FULL| SHOPS | 60 | 1260 | 3 (0)| 00:00:01 |
------------------------------------------------------------------------
QUERY PLAN
-------------------------------------------------------
Seq Scan on shops (cost=0.00..1.60 rows=60 width=22)
② ① ③
② ① ② ③
+----+-------------+-------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | type | possible_keys | key | key_len | re f | rows | filtered | Extra |
+----+-------------+-------+------+---------------+------+---------+------+------+----------+-------+
| 1 | SIMPLE | Shops | ALL | NULL | NULL | NULL | NULL | 60 | 100.00 | |
+----+-------------+-------+------+---------------+------+---------+------+------+----------+-------+
出力される情報のフォーマットは完全に同じではありませんが、
① 対象オブジェクト
今、
また、
② オブジェクトの操作
オブジェクトに対する操作は、Seq Scan
は
DBMSはランダムスキャンも選択肢として持ちますが、
③ 操作の対象となるレコード数
3つ目の重要な項目は、
データベースの鉄則 1
実行計画で重要な項目は、レコード数はテーブルの実件数と一致するとは限らない
なお、
ためしに、
ランダムアクセスの実行計画
先ほど実行した簡単なクエリにWHERE条件を付けます。
SELECT *
FROM Shops
WHERE shop_id = ‘00050’;
再度実行計画を見てみましょう
実行計画
----------------------------------------------------------
Plan hash value: 1968021522
② ① ③
----------------------------------------------------------------------------------------
| Id | Operation | Name | Rows | Bytes | Cost (%CPU)| Time |
----------------------------------------------------------------------------------------
| 0 | SELECT STATEMENT | | 1 | 21 | 1 (0)| 00:00:01 |
| 1 | TABLE ACCESS BY INDEX ROWID| SHOPS | 1 | 21 | 1 (0)| 00:00:01 |
|* 2 | INDEX UNIQUE SCAN | SYS_C004155 | 1 | | 0 (0)| 00:00:01 |
----------------------------------------------------------------------------------------
Predicate Information (identified by operation id):
---------------------------------------------------
2 - access("SHOP_ID"='00050')
QUERY PLAN
------------------------------------------------------
② ① ③
Seq Scan on shops (cost=0.00..1.75 rows=1 width=22)
Filter: (shop_id = '00050'::bpchar)
② ① ② ③
+----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+-------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | filtered | Extra |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+-------+
| 1 | SIMPLE | Shops | const | PRIMARY | PRIMARY | 5 | const | 1 | 100.00 | |
+----+-------------+-------+-------+---------------+---------+---------+-------+------+----------+-------+
3つの結果には、
操作の対象となるレコード数
まず、
対象オブジェクトと操作
オブジェクト
Oracleでは、TABLE ACCESS FULL
の代わりにTABLE ACCESS BY INDEX ROWID
と表示されINDEX UNIQUE SCAN
、SYS_
という見たことのないオブジェクトが出ていますSYS_
は主キーのインデックスの名前です。テーブル作成時に特に指定しなかったため、
MySQLのほうは、PRIMARY
が現れています。これも、
インデックススキャン
インデックスについては本稿では解説する紙幅がないため詳細は略しますが
シーケンシャルスキャンがデータ量に正比例的に処理コストが増大するのに対し、

今は60行しかデータが存在しないので、