Oracle のインデックス タイプには、非一意インデックス、一意インデックス、ビットマップ インデックス、ローカル プレフィックス パーティション インデックス、ローカル非プレフィックス パーティション インデックス、グローバル プレフィックス パーティション インデックス、ハッシュ パーティション インデックス、関数ベースのインデックスが含まれます。テーブルにデータを挿入した後、インデックスを作成する必要があります。一意のインデックスは、「create unique index」ステートメントで作成できます。
このチュートリアルの動作環境: Windows 7 システム、Oracle 11g バージョン、Dell G3 コンピューター。
インデックスとは何ですか?
インデックスの説明1) インデックスはデータベース オブジェクトの 1 つで、本のインデックスと同様に、データの検索を高速化するために使用されます。データベースにインデックスを作成すると、データベース プログラムが結果をクエリするときに読み取る必要のあるデータの量を減らすことができます。これは、書籍でインデックスを使用すると、本全体を読まなくても必要な情報を見つけることができるのと同様です。インデックスを使用する目的:#2) インデックスはテーブル上に構築されるオプションのオブジェクトです。インデックスの鍵は、デフォルトのフル テーブル スキャンの取得方法をソートされたインデックス キーのセットに置き換えることで、取得効率を向上させます
3) インデックスは、関連するテーブルやデータから論理的および物理的に独立しています。インデックスを作成または削除しても、基本テーブルには影響しません。
#4) インデックスが作成されると、それが実行されます。 DML 操作中 (たとえば、関連操作の挿入、変更、または削除を実行するとき)、Oracle は自動的にインデックスを管理し、インデックスの削除はテーブルには影響しません 5) インデックスは透過的ですテーブルに関係なく、ユーザーに対してインデックスが存在するかどうかにかかわらず、SQL ステートメントの使用法は変わりません6) Oracle は主キーの作成時に列にインデックスを自動的に作成します
クエリ速度の高速化
クエリによって返されるレコード数は、並べ替えられたテーブルの場合は 40% 未満、並べ替えられていないテーブルの場合は 7% 未満です。
非一意インデックス (最も一般的に使用される)
データをテーブルに挿入した後にインデックスを作成する
After SQL*Loader または
ソートされた大きなテーブルの 40%、またはソートされていないテーブルの 7% が頻繁に取得されます 行については、インデックスを構築することをお勧めします。テーブルの関連付け、インデックス列は結合に使用されます;
列の値は比較的一意です;多くの場合、レコードを取得するために複数のフィールドが一緒に使用され、結合されたインデックスは単一のインデックスよりも効率的です。最もよく使用される列を先頭に置きます。例: dx_groupid_serv_id(groupid,serv_id)
、、クエリはインデックスを使用します。
serv_id フィールドのみが使用される場合、インデックスは無効になります。
不要なインデックスを結合/分割してください。 。
テーブルには数百のインデックスを含めることができます (そうしますか?)。テーブルの挿入と更新を頻繁に行う場合、システム CPU のインデックスが増えるほど、I/O の負担が重くなります。
各テーブルのインデックスは 5 つ以下にすることをお勧めします。
アプリケーション内のクエリはインデックスを使用しません;
インデックスの並列作成を検討してください
initial
は 1M
、並列処理は 8
であり、少なくとも 8M
インデックスの作成中にスペースが消費されます;nologging
を使用してインデックスを作成することを検討してください
最適なインデックスを作成するにはどうすればよいですか?
インデックスを明示的に作成する
create index index_name on table_name(field_name) tablespace tablespace_name pctfree 5 initrans 2 maxtrans 255 storage ( minextents 1 maxextents 16382 pctincrease 0 );
関数ベースのインデックスを作成するインデックス:
UPPER、LOWER、TO_CHAR(date)
および他の関数分類でよく使用されます。例:
create index idx_func on emp (UPPER(ename)) tablespace tablespace_name;
ビットマップ インデックスの作成:
ベースを比較する 小さくて比較的安定したベースを持つ列のインデックスを作成する場合は、最初にビットマップ インデックスを考慮する必要があります。例:
create bitmap index idx_bitm on class (classno) tablespace tablespace_name;
一意のインデックスを明示的に作成する
create unique index
ステートメントを使用して、一意のインデックスを作成できます。例:
create unique index dept_unique_idx on dept(dept_no) tablespace idx_1;
制約に関連するインデックスの作成
using インデックスを使用できます。
ステートメント (unique
および primary key)
制約に関連するフィールドのインデックスを作成します。例:
alter table table_name add constraint PK_primary_keyname primary key (field_name) using index tablespace tablespace_name;
ローカル パーティション インデックスの作成方法
Create Index TG_CDR04_SERV_ID_IDX On TG_CDR04(SERV_ID) Pctfree 5 Tablespace TBS_AK01_IDX Storage ( MaxExtents 32768 PctIncrease 0 FreeLists 1 FreeList Groups 1 ) local /
レンジ パーティションのグローバル インデックスを作成する方法
基本テーブルには、グローバル テーブルとパーティション テーブルを使用できます。
create index idx_start_date on tg_cdr01(start_date) global partition by range(start_date) (partition p01_idx vlaues less than (‘0106’) partition p01_idx vlaues less than (‘0111’) … partition p01_idx vlaues less than (‘0401’ )) /
既存のインデックスの再構築
既存のインデックスを再構築する現時点では、クエリには影響しません。
インデックスを再構築すると、追加のデータ ブロックが削除される可能性があります。
クエリの効率が向上します。インデックス クエリ;
alter index idx_name rebuild nologging;
パーティション インデックスの場合:
alter index idx_name rebuild partition partiton_name nologging;
インデックスを削除する理由
<br/>dropindex idx_name; <br/>dropindexidx_namedroppartitionpartition_name; <br/>
インデックス確立のコスト
基本テーブルを維持する場合、システムはインデックスを同じ状態に維持する必要があります。不合理なインデックスは、主に CPU と I/O に現れるシステム リソースに深刻な影響を及ぼします。
データの挿入、更新、削除により、大量の db ファイル シーケンシャル読み取り
ロック待機が生成されます。
データが数百万個あり、特定のフィールドにインデックスを追加しましたが、クエリのパフォーマンスが向上しません。主に oracle## のインデックス制限が原因である可能性があります。 #。
oracle のインデックスにはいくつかのインデックス制限があります。これらのインデックス制限が発生すると、インデックスが追加されている場合でも、
oracle はフル テーブル スキャンを実行します。クエリのパフォーマンスは、インデックスを作成しない場合と比べて改善されず、データベース内のインデックスを維持するためのシステム オーバーヘッドにより、パフォーマンスが低下する可能性があります。
拡張知識: 一般的なインデックス制限の問題
1. 不等号演算子 (<>, != )# を使用します。 ##次の状況では、列
dept_id にインデックスがある場合でも、クエリ ステートメントは依然としてテーブル全体のスキャンを実行します<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="prettyprint">select * from dept where staff_num <> 1000;</pre><div class="contentsignin">ログイン後にコピー</div></div>
ただし、これは実際に必要です開発クエリでは、問題の解決策はありませんか? ######持っている!
不等号をクエリ構文の または に置き換えることで、インデックスを使用してテーブル全体のスキャンを回避できます。上記のステートメントを次のように変更すると、インデックスを使用できるようになります。
select * from dept shere staff_num < 1000 or dept_id > 1000;
is null または
is nuo null の使用も制限されますデータベースでは null
値が定義されていないため、インデックスを使用します。インデックス付きの列に多くの null がある場合、インデックスは使用されません (インデックスがビットマップ インデックスでない限り、これについては今後のブログ記事で詳しく説明します)。 SQL ステートメントで null
を使用すると、多くの問題が発生します。 この問題を解決する方法は、テーブルの作成時に、インデックスを付ける必要がある列を非 null (
not null
)
として定義することです。 3. 関数を使用します
関数ベースのインデックスが使用されていない場合、where 句のインデックス付き列で関数を使用すると、オプティマイザはこれらのインデックスを無視します。次のクエリではインデックスは使用されません:
select * from staff where trunc(birthdate) = '01-MAY-82';
但是把函数应用在条件上,索引是可以生效的,把上面的语句改成下面的语句,就可以通过索引进行查找。
select * from staff where birthdate < (to_date('01-MAY-82') + 0.9999);
4、比较不匹配的数据类型
比较不匹配的数据类型也是难于发现的性能问题之一。下面的例子中,dept_id
是一个varchar2
型的字段,在这个字段上有索引,但是下面的语句会执行全表扫描。
select * from dept where dept_id = 900198;
这是因为oracle
会自动把where
子句转换成to_number(dept_id)=900198
,就是3所说的情况,这样就限制了索引的使用。把SQL语句改为如下形式就可以使用索引
select * from dept where dept_id = '900198';
5、使用like子句
使用like子句查询时,数据需要把所有的记录都遍历来进行判断,索引不能发挥作用,这种情况也要尽量避免。
Like
的字符串中第一个字符如果是‘%’
则用不到索引
Column1 like ‘aaa%’ 是可以的 Column1 like ‘%aaa%’用不到
6、使用IN
尽管In
写法要比exists
简单一些,exists
一般来说性能要比In要高的多
用In
还是用Exists
的时机
当in的集合比较小的时候,或者用Exists
无法用到选择性高的索引的时候,用In要好,否则就要用Exists
例:
select count(*) from person_info where xb in (select xb_id from dic_sex); Select count(*) from n_acntbasic a where shbxdjm =:a and exists(select 1 from person_info where pid=a.pid and …); Select * from person_info where zjhm=3101….;--将会对person_info全表扫描 Select * from person_info where zjhm =‘3101…’;--才能用到索引
假定TEST表的dt
字段是date
类型的并且对dt
建了索引。
如果要查‘20041010’
一天的数据.下面的方法用不到索引
Select * from test where to_char(dt,’yyyymmdd’) =‘20041010’;
而以下将会用到索引。
select * from test where dt >=to_date(‘20041010’,’yyyymmdd’) and dt < to_date(‘20041010’,’yyyymmdd’) + 1
7、如果能不用到排序,则尽量避免排序。
用到排序的情况有
集合操作。Union ,minus ,intersect
等,注:union all
是不排序的。
Order byGroup byDistinctIn
有时候也会用到排序
确实要排序的时候也尽量要排序小数据量,尽量让排序在内存中执行,有文章说,内存排序的速度是硬盘排序的1万倍。
在排序的字段上创建索引,让排序在内存中执行,加快排序速度。
8、在基于CBO的优化器(花费)下,表的统计数据过期。也可能导致不使用索引。
解决:执行表分析。获取表的最新信息。
9、获取的数据量过大,全部扫描效率更高
10、索引字段的值分散率太低,值太集中,如类型字段都是1,2, 状态类型Y-有效/N-无效。这类型的字段最好别建索引。
尽管在这些字段上建立了索引,但对全表数据区分度不大。最后还是会全表扫描。
推荐教程:《Oracle教程》
以上がOracle にはどのようなインデックスがありますか?の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。