by Hayato Matsuura

複合インデックス



調    (  )  使

 EMPLOYEES10  EMPLOYEE_ID  ID  EMPLOYEE_ID  SUBSIDIARY_ID2


CREATE UNIQUE INDEX employees_pk
    ON employees (employee_id, subsidiary_id)

 SUBSIDIARY_ID
SELECT first_name, last_name
  FROM employees
 WHERE employee_id   = 123
   AND subsidiary_id = 30

使INDEX  UNIQUE SCAN使使  
SELECT first_name, last_name
  FROM employees
 WHERE subsidiary_id = 20

使TABLE ACCESS FULLwhere  10TABLE ACCESS FULL  10    

フルテーブルスキャン


TABLE ACCESS FULL    

TABLE ACCESS FULL    FULL TABLE SCAN  ()  

複合インデックスから任意の1つの列を選んで使う事はできないので、 データベースはインデックスを使いません。インデックスの構造をより深く見ていくと、この理由がはっきりします。

協力してください

この記事が気に入ったら、私の書いた本「SQLパフォーマンス詳解」や私によるトレーニングもきっと気にいるはず。

複合インデックスは、ソートされたリストにインデックスのデータを 保存する他のインデックスと同じく、Bツリーインデックスです。データベースは、 インデックスのエントリをソートするのに、インデックスの定義に書かれた順序に従って列を識別します。最初の列は並べ替えの優先順位が最も 高く、最初の列に同じ値が複数ある時に限り、2番目の列でも並べ替えがされます。

重要

複合インデックスは、複数の列にまたがるひとつの インデックスのことです。


2  22

図2.1複合インデックス

123123123202127ROWIDROWIDROWID123124125302011ROWIDROWIDROWID12312312512618271119121126131251911インデックスEMPLOYEE_IDSUBSIDIARY_IDEMPLOYEE_IDSUBSIDIARY_IDEMPLOYEE_IDSUBSIDIARY_ID

図2.1 はインデックスの一部を表したものです。子会社ID 20のエントリは、隣同士に保存されているわけではありません。リーフノードにエントリは存在して いますが、SUBSIDIARY_ID = 20としてアクセスできるエントリが まとまっているわけではないことが分かるでしょう。このようなツリーでは、2番目の列だけで検索するクエリは役に立たないのです。

ヒント


 使  (SQL:2008LIMIT  TOPROWNUM使 syntax of top-n queries)
SELECT <INDEX COLUMN LIST> 
  FROM <TABLE>  
 ORDER BY <INDEX COLUMN LIST>
 FETCH FIRST 100 ROWS ONLY

   

SUBSIDIARY_ID  EMPLOYEE_ID  

使    SUBSIDIARY_ID
CREATE UNIQUE INDEX EMPLOYEES_PK 
    ON EMPLOYEES (SUBSIDIARY_ID, EMPLOYEE_ID)

2INDEX  UNIQUE SCAN  SUBSIDIARY_ID  B使  

重要

複合インデックスを定義する際に考えるべき最も重要なのは、そのインデックスを使えるSQL文ができるだけ多くなるように、 列の順番を決めることです。


使  SUBSIDIARY_ID    INDEX RANGE SCAN

DB2

Explain Plan
-------------------------------------------------------------
ID | Operation               |                    Rows | Cost
 1 | RETURN                  |                         |  128
 2 |  FETCH EMPLOYEES        |  1195 of 1195 (100.00%) |  128
 3 |   RIDSCN                |  1195 of 1195 (100.00%) |   43
 4 |    SORT (UNIQUE)        |  1195 of 1195 (100.00%) |   43
 5 |     IXSCAN EMPLOYEES_PK | 1195 of 10000 ( 11.95%) |   43

Predicate Information
 2 - SARG (Q1.SUBSIDIARY_ID = +00002.)
 5 - START (Q1.SUBSIDIARY_ID = +00002.)
      STOP (Q1.SUBSIDIARY_ID = +00002.)


使  IXSCAN  FETCH  SORTRIDSCN  SORT    RIDSCAN  (IO)

MySQL

+----+-----------+------+---------+---------+------+-------+
| id | table     | type | key     | key_len | rows | Extra |
+----+-----------+------+---------+---------+------+-------+
|  1 | employees | ref  | PRIMARY | 5       |  123 |       |
+----+-----------+------+---------+---------+------+-------+

MySQLrefOracleINDEX RANGE  SCAN

Oracle

---------------------------------------------------------------
|Id |Operation                   | Name         | Rows | Cost |
---------------------------------------------------------------
| 0 |SELECT STATEMENT            |              |  106 |   75 |
| 1 | TABLE ACCESS BY INDEX ROWID| EMPLOYEES    |  106 |   75 |
|*2 |  INDEX RANGE SCAN          | EMPLOYEES_PK |  106 |    2 |
---------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------
   2 - access("SUBSIDIARY_ID"=20)


PostgreSQL

                 QUERY PLAN
----------------------------------------------
 Bitmap Heap Scan on employees
 (cost=24.63..1529.17 rows=1080 width=13)
   Recheck Cond: (subsidiary_id = 2::numeric)
   -> Bitmap Index Scan on employees_pk
      (cost=0.00..24.36 rows=1080 width=0)
      Index Cond: (subsidiary_id = 2::numeric)

PostgreSQLBitmap Index Scan  Bitmap Heap Scan2  OracleINDEX RANGE  SCANTABLE ACCESS BY INDEX ROWID  1Bitmap Index  ScanBitmap Heap  Scan  IO

SQL Server

|--Nested Loops(Inner Join)
   |--Index Seek(OBJECT:employees_pk,
   |               SEEK:subsidiary_id=20
   |            ORDERED FORWARD)
   |--RID Lookup(OBJECT:employees,
                   SEEK:Bmk1000=Bmk1000
                 LOOKUP ORDERED FORWARD)


()使3  112  使

2select  1  2  insertdeleteupdate

協力してください

この記事が気に入ったら、私の書いた本「SQLパフォーマンス詳解」や私によるトレーニングもきっと気にいるはず。


   where  

   1      

   
前へ次へ

You can’t learn everything in one day. Subscribe the newsletter via E-Mail, Twitter or RSS to gradually catch up. Have a look at modern-⁠sql.com as well.

著者について

Markus Winandの写真

 Markus WinandSQLSQL Performance Explained  http://winand.at/  

彼の本

カバー『SQLパフォーマンス詳解』

核心をわかりやすく 解説。

Markusから購入します
(送料無料+PDF)

Amazon.co.jpで購入
(印刷版のみ)

Connect with Markus Winand

Markus Winand MailinglistsSubscribe RSS feedMarkus Winand on LinkedInMarkus Winand on XINGMarkus Winand on TwitterMarkus Winand on Bluesky

Copyright 2015-2024 Hayato Matsuura, Markus Winand. All righs reserved.
法律上の通知 | お問い合わせ | 無保証 | 商標 | プライバシーとGDPR