SQLでのインデックス作成方法|SQLServerなどのDBでのやり方を解説

- システム
エンジニア - インデックスって聞いたことがあるのですが、具体的にはどのような役割を担っているのでしょうか?
- プロジェクト
リーダー - 一言でいうと「目次」の働きをしてくれます。テーブルに目次を付けるというイメージでインデックスについて確認していきましょう。
インデックスとは
システム開発やプログラミングに携わったことがないという人でも、「インデックス」という言葉を使ったり聞いたりしたことがあるでしょう。目次に対して、「あいうえお」や「ABC」などの言葉順にページを探せるものを「索引」「インデックス」と呼んでいます。
データベースで使われる「インデックス」も、書物の「インデックス」と同じように、情報を引き出すための「索引」として使われる仕組みです。
インデックスを作成するメリット・デメリット
データベースのインデックスは、必ず作成されている機能ではありません。システムの設計段階で、データベース項目ごとにインデックスを作成するか検討します。
インデックスを作成すると、検索速度があがります。データ量が多いほど、インデックスの有無で結果を得られるスピードが顕著になります。逆に、データ登録では、インデックスを作成する処理が必要になるので、その分、パフォーマンスが落ちてしまいます。
SQL Serverのインデックス作成方法
SQL Severのインデックスは大きく分けて2種類あります。それは「クラスター化インデックス」と「非クラスター化インデックス」です。
クラスター化インデックス
テーブルに格納されているレコードをインデックスで指定した列の値で並び替えて格納します。値が同じ場合は、2番目に指定した列の値で並び替えます。このクラスター化インデックスは、テーブルに対して1つしか作成できません。
非クラスター化インデックス
レコードの並び替えは行われずにテーブルに格納されています。インデックスで指定した列の値に対応するレコードへのポインタがインデックスファイルに格納されます。テーブルに対して複数のインデックスを付与することができるのも特徴のひとつです。
PostgreSQLでのインデックスの使い方4つ
ここでは、個人の学習用としても、企業の業務システムとしても、使われることの多い「PostgreSQL」で、インデックスを利用する方法を紹介します。
以下のコードを実行して作成されるテーブルを想定して、PostgreSQLのインデックス作成手順を解説します。
例)smplスキーマにjushoテーブルを作成
1
2
3
4
5
|
create table smpl.jusho(
id integer,
name varchar(10),
address varchar(20)
);
|
インデックスの作成方法
PostgreSQLのテーブルにインデックスを作成する基本構文は以下のとおりです。
1
|
CREATE INDEX インデックス名 ON [ ONLY ] テーブル名 ( カラム名... )
|
例)jushoテーブルのaddress にインデックスを作成する
1
|
CREATE INDEX idx_address ON smpl.jusho(address );
|
カンマ区切りで複数指定したい場合の作成方法
PostgreSQLで作成できるインデックスは項目単位だけでなく、複数の項目を組み合わせることも可能です。基本構文の「カラム名」を指定している箇所で、複数のカラム名を指定すると、複合キーとして利用できます。カラム名は「,(カンマ)」で区切って複数記述します。
例)nameとaddressで1つのインデックスを作成
1
|
CREATE INDEX idx_name_address ON smpl.jusho(name,address );
|
¥diコマンドを使ってインデックスを確認する方法
PostgreSQLでは、¥diコマンドを使って、作成したインデックスの一覧を取得できます。¥diコマンドを使う前に、インデックス一覧を取得したいデータベースに接続しておきましょう。¥diコマンドを実行すると、インデックス名と所有者、テーブル名などが一覧表示されます。
作成したスキーマのインデックスリストを確認したい場合
接続したデータベースで¥diコマンドを実行すると、対象データベースに作成されているすべてのインデックスがスキーマ、テーブル、所有者ごとに表示されます。
自分が利用しているスキーマに作成されているインデックス一覧だけが必要な場合は、以下のようにコマンドを発行します。
例)smplスキーマのインデックスのみを表示させる
1
2
3
4
5
|
¥di smpl.*
Schema | Name | Type | Owner | Table
--------+------------------+-------+----------+---------
smpl | idx_name_address | index | postgres | jusho
|
更に詳細にインデックスの確認をしたい場合
PostgreSQLで作成したインデックスの一覧だけでなく、各インデックスの詳細な情報を参照したいときは、¥dコマンドを使用します。¥dコマンドを使うと、インデックスを構成するカラム名やデータ型など、テーブル項目の詳細情報が表示されます。
¥dの後ろに参照したいインデックス名かテーブル名を指定します。
例)インデックス名を指定
1
2
3
4
5
6
7
8
|
¥di idx_name_address
Index "smpl.idx_name_address"
Column | Type | Key? | Definition
--------+-----------------------+------+------------
name | character varying(10) | yes | name
address| character varying(20) | yes | address
, for table "smpl.jusho"
|
インデックスを削除する方法
作成したインデックスに誤りがあったり不要になったりしたときは、「DROP INDEX インデックス名」構文でインデックスを削除できます。インデックスを削除しても、テーブルそのものや、テーブルに保存されているデータには影響ありません。
例)smplスキーマのインデックスidx_nameを削除する
1
|
DROP INDEX smpl.idx_name;
|
Oracle Databaseでのインデックスの使い方
Oracle Databaseでインデックスを作成・削除するためのSQL文は、PostgreSQLを利用するときの構文と似ています。Oracleには「表領域」という概念があるので、構文の末尾に表領域の指定を記載します。
例)インデックス用表領域idx_spにインデックスを作成する
1
|
CREATE INDEX idx_name ON smpl.jusho(name) TABLESPACE idx_sp;
|
インデックスの効果があまりないパターン6つ
インデックスを利用するとデータ検索のパフォーマンスがあがるはずですが、インデックスを実際に作成してみると、想定していたほど効果があらわれないこともあります。
ここでは、インデックスの効果が発揮されない原因や理由を紹介します。効果がみられないインデックスを見直してみましょう。
インデックスで演算を使っている場合
インデックスを作成した項目使って、SQL文の中で演算を行っていると、インデックスは無効となるため、パフォーマンスがあがりません。
5教科の平均点が50点を超える生徒のみを抽出する以下のSQL文では、総得点totalにインデックスを作成しても「/5」という計算式を使っているのでインデックスは無効になります。インデックスと関係ない式の右側に演算を用いると、インデックスが活かされます。
1
2
|
× SELECT name FROM seiseki WHERE total/ 5 > 50
〇 SELECT name FROM seiseki WHERE total > 50 * 5(250)
|
インデックスで否定形を使っている場合
SQL文の検索条件が否定形の場合、インデックスが活かされません。「~ではない」という条件では、条件に合ったデータを直接検索することができず、全件検索することになってしまいます。
例)総得点が0点ではない人を検索する(<>や!=など否定形は全件検索が行われる)
1
|
SELECT name FROM seiseki WHERE total <> 0
|
インデックスでIS NULLを使っている場合
指定した項目にデータが存在しないレコードのみを検索したいときに、SQL文で「IS NULL」という条件を使いますが、NULLについてもインデックスが使えません。データ不存在の条件をSQL文で利用する可能性がある場合は、ダミーデータを設定しておくことをおすすめします。
インデックスで関数処理を使っている場合
SQL文の検索条件となるWhere句の中で関数を使っている場合、インデックスを作成した項目を演算するのと同じ意味合いになるので、インデックスが無効となります。SQL文の中でインデックスを作成した項目に関数を使うのも避けましょう。
ORを使っている場合
SQL文のWhere句でORを使ってしまうとインデックスが使われません。複数の条件のいずれかに合致すれば抽出するので、全件検索になってしまいます。
インデックスを活かすSQL文として、Oracleの場合は、ORで条件をつながずに条件ごとのSQL文を書き、UNION ALLで結果を合体させられます。
LIKEの部分一致検索を使っている場合
SQL文のWhere句で、部分一致の条件として使えるLIKE文も、使い方に注意が必要です。前方一致の場合はインデックスが有効になりますが、中間一致や後方一致は全件検索になってしまいます。
例)インデックス有効:〇 無効:×
1
2
3
|
〇 SELECT id,name FROM jusho WHERE name LIKE '鈴木一%'
× SELECT id,name FROM jusho WHERE name LIKE '%木一%'
× SELECT id,name FROM jusho WHERE name LIKE '%一郎'
|
- システム
エンジニア - インデックスって目次のような働きをしてくれるのですね。これからは積極的に活用していきます。
- プロジェクト
リーダー - 本も目次があると、読みたい内容がどこにあるかすぐに分かると思います。それと一緒でテーブルに対してインデックスを付与してあげると、検索スピードが当然上がります。検索画面で検索結果がなかなか返ってこないプログラムを作らないように、インデックスを付与することは忘れずに行いたいところですね。
SQL インデックス検索のパフォーマンスを考えたテーブル設計を行いましょう
今回はSQL Serverでのインデックスがメインでしたが、インデックス自体は他のデータベースにも存在します。インデックスの概念を理解しておけば、検索のパフォーマンスを考慮したテーブルの作成をどのデータベースに対しても行えます。
エンジニアとしてテーブル設計に携わる機会が訪れた時には、ぜひインデックスは有効活用するように心がけましょう。
FEnet.NETナビ・.NETコラムは株式会社オープンアップシステムが運営しています。
株式会社オープンアップシステムはこんな会社です
秋葉原オフィスには株式会社オープンアップシステムをはじめグループのIT企業が集結!
数多くのエンジニアが集まります。

-
スマホアプリから業務系システムまで
スマホアプリから業務系システムまで開発案件多数。システムエンジニア・プログラマーとしての多彩なキャリアパスがあります。
-
充実した研修制度
毎年、IT技術のトレンドや社員の要望に合わせて、カリキュラムを刷新し展開しています。社内講師の丁寧なサポートを受けながら、自分のペースで学ぶことができます。
-
資格取得を応援
スキルアップしたい社員を応援するために資格取得一時金制度を設けています。受験料(実費)と合わせて資格レベルに合わせた最大10万円の一時金も支給しています。
-
東証プライム上場企業グループ
オープンアップシステムは東証プライム上場「株式会社夢真ビーネックスグループ」のグループ企業です。
安定した経営基盤とグループ間のスムーズな連携でコロナ禍でも安定した雇用を実現させています。
株式会社オープンアップシステムに興味を持った方へ
株式会社オープンアップシステムでは、開発系エンジニア・プログラマを募集しています。
年収をアップしたい!スキルアップしたい!大手の上流案件にチャレンジしたい!
まずは話だけでも聞いてみたい場合もOK。お気軽にご登録ください。


SQLServer新着案件New Job
-
蔦屋書新店オープンに関するアプリ開発/Oracle/東京都渋谷区/【WEB面談可】/在宅勤務
月給56万~59万円東京都渋谷区(神泉駅) -
資産運用会社向け残高管理システム運用保守/SQLServer/東京都中央区/【WEB面談可】
月給50万~60万円東京都中央区(銀座駅) -
資産運用会社向け残高管理システム開発のテスター/SQLServer/東京都中央区/【WEB面談可】
月給25万~35万円東京都中央区(銀座駅) -
放射線部門システムパッケージの運用保守/Oracle/東京都港区/【WEB面談可】
月給50万~60万円東京都港区(品川駅) -
放射線部門システムパッケージの開発のテスター/Oracle/東京都港区/【WEB面談可】
月給25万~35万円東京都港区(品川駅) -
営業フロントシステム運用保守/ASP.NET/東京都江東区/【WEB面談可】
月給50万~60万円東京都江東区(木場駅)