Maison > base de données > Oracle > le corps du texte

De quels index Oracle dispose-t-il ?

青灯夜游
Libérer: 2022-05-18 20:38:52
original
8231 Les gens l'ont consulté

Les types d'index d'Oracle incluent : l'index non unique, l'index unique, l'index bitmap, l'index de partition de préfixe local, l'index de partition local sans préfixe, l'index de partition de préfixe global, l'index de partition de hachage et l'index basé sur les fonctions. L'index doit être créé après l'insertion des données dans la table. Un index unique peut être créé avec l'instruction "create unique index".

De quels index Oracle dispose-t-il ?

L'environnement d'exploitation de ce tutoriel : système Windows 7, version Oracle 11g, ordinateur Dell G3.

Qu'est-ce qu'un indice ?

  • Un index est un objet auxiliaire construit sur une ou plusieurs colonnes d'une table, dans le but d'accélérer l'accès aux données de la table.
  • La structure des données de l'index de stockage Oracle est un arbre B* (arbre équilibré) ; ), index bitmap La même chose est vraie, mais les nœuds feuilles ont des index numériques B* différents
  • L'index se compose du nœud racine, du nœud branche et du nœud feuille. Le bloc d'index de niveau supérieur contient les données d'index du nœud inférieur. -bloc d'index de niveau, et le nœud feuille contient les données d'index et détermine la position réelle de la ligne.

Description de l'index

1) L'index est l'un des objets de base de données, utilisé pour accélérer la récupération des données, similaire à l'index d'un livre. L'indexation dans une base de données peut réduire la quantité de données qu'un programme de base de données doit lire lors de l'interrogation des résultats, de la même manière que dans les livres, nous pouvons utiliser les index pour trouver les informations souhaitées sans avoir à lire le livre en entier.

2) L'index est un objet facultatif construit sur la table ; la clé pour indexer est de remplacer la méthode de récupération par défaut de l'analyse complète de la table par un ensemble de clés d'index triées, améliorant ainsi l'efficacité de la récupération

3) L'index est logique et physique, cela n'a rien à voir avec les tables et données associées. Lors de la création ou de la suppression d'un index, cela n'affectera pas la table de base 

4) Une fois l'index établi, lors de l'exécution d'opérations DML sur la table (telles que l'insertion, la modification) , ou suppression) Lors des opérations associées), Oracle gérera automatiquement l'index et la suppression de l'index n'affectera pas la table

5) L'index est transparent pour l'utilisateur, qu'il y ait ou non un index sur la table, son utilisation. de l'instruction SQL reste inchangée.

6) Création Oracle Lorsque la clé primaire est utilisée, un index sera automatiquement créé sur la colonne

Le but de l'utilisation de l'index :

  • Accélérer vitesse de requête
  • Réduire les opérations d'E/S
  • Éliminer le tri des disques (les index peuvent accélérer le tri)

Quand utiliser les index :

  • Le nombre d'enregistrements renvoyés par la requête est
  • La table est plus fragmentée (ajouts et suppressions fréquents)

Types d'index

  • Index non unique (le plus couramment utilisé)
  • Index unique
  • Index Bitmap
  • Index de partition préfixé local
  • Index partitionné local sans préfixe
  • Index partitionné préfixé global
  • Index partitionné par hachage
  • Index basé sur les fonctions

Directives pour la gestion des index

  • Créer un index après avoir inséré des données dans la table
  • Insérez ou chargez des données à l'aide de SQL*Loader ou de l'outil import Enfin, l'indexation est plus efficace import工具插入或装载数据后,建立索引比较有效;

索引正确的表和列

  • 经常检索排序大表中40%或非排序表7%的行,建议建索引;
  • 为了改善多表关联,索引列用于联结;
  • 列中的值相对比较唯一;
  • 取值范围(大:B*树索引,小:位图索引);
  • Date型列一般适合基于函数的索引;
  • 列中有许多空值,不适合建立索引

为性能而安排索引列

  • 经常一起使用多个字段检索记录,组合索引比单索引更有效;
  • 把最常用的列放在最前面,例:dx_groupid_serv_id(groupid,serv_id),在where条件中使用groupidgroupid,serv_id,查询将使用索引,若仅用到serv_id

Indexez les bonnes tables et colonnes

Récupérez souvent 40% des lignes d'une grande table triée ou 7% d'une table non triée, il est recommandé de construire un index

    Afin d'améliorer l'association de plusieurs tables, la colonne d'index est utilisée pour la jointure ;
  • La valeur dans la colonne est relativement unique ;

    Plage de valeurs (grande : index d'arbre B*, petite : index bitmap) ;
  • La colonne de type Date convient généralement à l'index basé sur une fonction ;

    Il existe de nombreuses valeurs nulles ; ​dans la colonne, qui ne convient pas à l'indexation

Organisez les colonnes d'index pour les performances

  • Plusieurs champs sont souvent utilisés ensemble pour récupérer des enregistrements, et les index combinés sont plus efficaces que les index simples
  • mettez le ; Les colonnes les plus couramment utilisées sont placées au premier plan, par exemple : dx_groupid_serv_id(groupid,serv_id), utilisez groupid ou groupid dans <code>where condition, serv_id, la requête utilisera l'index Si seul le champ serv_id est utilisé, l'index sera invalide ;

  • Fusionner/diviser les index inutiles.

Limiter le nombre d'index par table

🎜Une table peut avoir des centaines d'index (feriez-vous cela ?), mais pour des insertions et des mises à jour fréquentes de la table, plus le processeur du système a d'index, I/ O Plus la charge est lourde 🎜🎜🎜🎜 Il est recommandé que chaque table ne comporte pas plus de 5 index. 🎜🎜🎜🎜🎜Supprimer les index qui ne sont plus nécessaires🎜🎜🎜🎜🎜Index invalides, principalement en raison de l'utilisation d'index basés sur des fonctions ou d'index bitmap au lieu d'index arborescents B* 🎜🎜🎜🎜Les requêtes dans les applications ne sont pas valides ; Utilisez index ; 🎜🎜🎜🎜Vous devez supprimer l'index avant de reconstruire l'index. Si vous utilisez alter index...rebuild pour reconstruire l'index, vous n'avez pas besoin de supprimer l'index. 🎜🎜🎜🎜🎜Indexer l'utilisation de l'espace des blocs de données🎜🎜
  • Spécifiez l'espace table lors de la création d'un index, en particulier lors de la création d'une clé primaire.
  • Définissez raisonnablement pctfress Remarque : pctused ne peut pas être spécifié pour l'index ; et définissez les paramètres de stockage de manière raisonnable. La valeur par défaut est la taille de l'espace table, ou initial et next sont définis sur la même taille.
Envisagez de créer des index en parallèle

La création d'index en parallèle peut être utilisée pour les grandes tables. Lors de la création d'index en parallèle, les paramètres de stockage sont utilisés séparément par chaque processus du serveur de requêtes, par exemple : initial est 1M, le parallélisme est 8, alors au moins 8M sera consommé lors de la création de l'index
  • initial1M,并行度为8,则创建索引期间至少要消耗8M空间;

考虑用nologging创建索引

  • 对大表创建索引可以使用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
  );
Copier après la connexion

创建基于函数的索引:

常用与UPPER、LOWER、TO_CHAR(date)等函数分类上,例:

create index idx_func on emp (UPPER(ename)) tablespace tablespace_name;
Copier après la connexion

创建位图索引:

对基数较小,且基数相对稳定的列建立索引时,首先应该考虑位图索引,例:

create bitmap index idx_bitm on class (classno) tablespace tablespace_name;
Copier après la connexion

明确地创建唯一索引

可以用create unique index语句来创建唯一索引,例:

create unique index dept_unique_idx on dept(dept_no) tablespace idx_1;
Copier après la connexion

创建与约束相关的索引

可以用using index字句,为与uniqueprimary key约束相关的字段创建索引,例如:

alter table table_name
  add constraint PK_primary_keyname primary key (field_name)
  using index tablespace tablespace_name;
Copier après la connexion

如何创建局部分区索引

  • 基础表必须是分区表;
  • 分区数量与基础表相同;
  • 每个索引分区的子分区数量与相应的基础表分区相同;
  • 基础表的子分区中的行的索引项,被存储在该索引的相应的子分区中,例如:
  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  /
Copier après la connexion

如何创建范围分区的全局索引

基础表可以是全局表和分区表。

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’ ))
  /
Copier après la connexion

  重建现存的索引
  重建现存的索引的当前时刻不会影响查询;

  重建索引可以删除额外的数据块;
  提高索引查询效率;

alter index idx_name rebuild nologging;
Copier après la connexion

  对于分区索引:

alter index idx_name rebuild partition partiton_name nologging;
Copier après la connexion

要删除索引的原因

  • 不再需要的索引;
  • 索引没有针对其相关的表所发布的查询提供所期望的性能改善;
  • 应用没有用该索引来查询数据;
  • 该索引无效,必须在重建之前删除该索引;
  • 该索引已经变的太碎了,必须在重建之前删除该索引;
  • 语句:<br/> drop index idx_name; <br/> drop index idx_name drop partition partition_name; <br/>

建立索引的代价

基础表维护时,系统要同时维护索引,不合理的索引将严重影响系统资源,主要表现在CPU和I/O上;

插入、更新、删除数据产生大量db file sequential read锁等待;

一个表中有几百万条数据,对某个字段加了索引,但是查询时性能并没有什么提高,这主要可能是oracle的索引限制造成的。

oracle的索引有一些索引限制,在这些索引限制发生的情况下,即使已经加了索引,oracle还是会执行一次全表扫描,查询的性能不会比不加索引有所提高,反而可能由于数据库维护索引的系统开销造成性能更差。

扩展知识:常见的索引限制问题

1、使用不等于操作符(<>, !=)

下面这种情况,即使在列dept_id有一个索引,查询语句仍然执行一次全表扫描

select * from dept where staff_num <> 1000;
Copier après la connexion

但是开发中的确需要这样的查询,难道没有解决问题的办法了吗?

有!

通过把用 or 语法替代不等号进行查询,就可以使用索引,以避免全表扫描:上面的语句改成下面这样的,就可以使用索引了。

select * from dept shere staff_num < 1000 or dept_id > 1000;
Copier après la connexion

2、使用 is null 或 is not null

使用 is nullis nuo null也会限制索引的使用,因为数据库并没有定义null值。如果被索引的列中有很多null,就不会使用这个索引(除非索引是一个位图索引,关于位图索引,会在以后的blog文章里做详细解释)。在sql语句中使用null会造成很多麻烦。

解决这个问题的办法就是:建表时把需要索引的列定义为非空(not null)

3、使用函数

如果没有使用基于函数的索引,那么where

Envisagez d'utiliser nologging</code > Créer un index 🎜🎜🎜🎜 Vous pouvez utiliser nologging pour réduire les journaux de rétablissement lors de la création d'index pour de grandes tables 🎜🎜 Économisez de l'espace dans les fichiers de journalisation 🎜🎜 Réduisez le temps de création des index ; lors de la création de grands index en parallèle . 🎜🎜🎜<span style="font-size: 18px;"><strong>Comment créer le meilleur index ?</strong></span>🎜🎜Créer des index explicitement🎜<div class="code" style="position:relative; padding:0px; margin:0px;"><div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="prettyprint">select * from staff where trunc(birthdate) = &amp;#39;01-MAY-82&amp;#39;;</pre><div class="contentsignin">Copier après la connexion</div></div><div class="contentsignin">Copier après la connexion</div></div>🎜Créer des index basés sur des fonctions :🎜🎜 Couramment utilisé avec <code>UPPER, LOWER, TO_CHAR(date) et d'autres fonctions, par exemple : 🎜
select * from staff where birthdate < (to_date(&#39;01-MAY-82&#39;) + 0.9999);
Copier après la connexion
Copier après la connexion
🎜Création d'un index bitmap :🎜🎜Lors de la création d'un index pour une colonne avec une petite base et une base relativement stable base, les premiers index Bitmap doivent être pris en compte, par exemple : 🎜
select * from dept where dept_id = 900198;
Copier après la connexion
Copier après la connexion
🎜 Créer explicitement un index unique 🎜🎜 Vous pouvez utiliser l'instruction create unique index pour créer un index unique, par exemple : 🎜
select * from dept where dept_id = &#39;900198&#39;;
Copier après la connexion
Copier après la connexion
🎜 Create un index lié à une contrainte 🎜🎜 Vous pouvez utiliser la clause using index pour créer un index pour les champs liés à l'unique et à la clé primaire des contraintes, par exemple : 🎜
Column1 like ‘aaa%’ 是可以的
Column1 like ‘%aaa%’用不到
Copier après la connexion
Copier après la connexion
🎜Comment créer un index de partition local🎜 🎜🎜La table de base doit être une table partitionnée 🎜🎜Le nombre de partitions est le même que la table de base 🎜🎜Le nombre de sous-partitions de chaque index ; la partition est la même que la partition de la table de base correspondante ; 🎜🎜Les entrées d'index des lignes dans les sous-partitions de la table de base, sont stockées dans la sous-partition correspondante de l'index, par exemple : 🎜🎜
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…’;--才能用到索引
Copier après la connexion
Copier après la connexion
🎜Comment créer un index global partitionné par plage🎜🎜La table de base peut être une table globale et une table partitionnée. 🎜
Select * from test where to_char(dt,’yyyymmdd’) =‘20041010’;
Copier après la connexion
Copier après la connexion
🎜 Reconstruire l'index existant
La reconstruction de l'index existant à l'heure actuelle n'affectera pas la requête ; 🎜🎜 La reconstruction de l'index peut supprimer des blocs de données supplémentaires
Améliorer l'efficacité des requêtes d'index ; 🎜
select * from test where dt >=to_date(‘20041010’,’yyyymmdd’) and dt < to_date(‘20041010’,’yyyymmdd’) + 1
Copier après la connexion
Copier après la connexion
🎜 Pour les partitions ; index : 🎜
Order byGroup byDistinctIn
Copier après la connexion
Copier après la connexion
🎜Raison de la suppression de l'index🎜🎜🎜L'index n'est plus nécessaire 🎜🎜L'index ne fournit pas l'amélioration des performances attendue pour les requêtes émises par ses tables associées 🎜🎜L'application n'utilise pas l'index pour interroger ; data;🎜🎜 L'index n'est pas valide et doit être supprimé avant la reconstruction ; 🎜🎜L'index est devenu trop fragmenté et l'index doit être supprimé avant la reconstruction ; 🎜🎜Déclaration : <br/> drop index idx_name ; > drop index idx_name drop partition partition_name; <br/>🎜🎜🎜Le coût de l'indexation🎜🎜Basique table Pendant la maintenance, le système doit maintenir l'index en même temps. Des index déraisonnables affecteront sérieusement les ressources du système, principalement sur le processeur et les E/S 🎜🎜L'insertion, la mise à jour et la suppression de données génèrent une grande quantité de fichier db ; lecture séquentielle Verrouillage en attente ; 🎜🎜Il y a des millions de données dans une table et un index est ajouté à un certain champ, mais les performances de la requête ne se sont pas améliorées. Cela peut être principalement dû à la limitation de l'index de. oracle. 🎜🎜 L'index de oracle a certaines restrictions d'index. Lorsque ces restrictions d'index se produisent, même si l'index a été ajouté, oracle effectuera toujours une analyse et une requête complètes de la table. Les performances ne seront pas améliorées par rapport à l’absence d’ajout d’index. Au lieu de cela, les performances peuvent être pires en raison de la surcharge du système liée à la maintenance de l’index dans la base de données. 🎜🎜Connaissances approfondies : problèmes courants de limitation d'index🎜🎜1. Utilisez l'opérateur d'inégalité (<> ;, !=)🎜🎜Dans la situation suivante, même s'il y a un index sur la colonne dept_id, l'instruction de requête effectue toujours une analyse complète de la table🎜rrreee🎜Mais une telle requête est effectivement nécessaire en développement, n'y a-t-il pas de solution au problème ? 🎜🎜Oui ! 🎜🎜En remplaçant le signe d'inégalité par la syntaxe ou pour l'interrogation, vous pouvez utiliser un index pour éviter une analyse complète de la table : remplacez l'instruction ci-dessus par la suivante et vous pouvez utiliser l'index. 🎜rrreee🎜2. Utiliser est nul ou n'est pas nul🎜🎜Utiliser est nul ou est nuo nul limitera également l'utilisation des index, car la base de données ne définit pas la valeur null. S'il y a beaucoup de valeurs nulles dans la colonne indexée, l'index ne sera pas utilisé (sauf si l'index est un index bitmap, ce qui sera expliqué en détail dans un prochain article de blog). L'utilisation de null dans les instructions SQL causera beaucoup de problèmes. 🎜🎜La façon de résoudre ce problème est la suivante : lors de la création de la table, définissez les colonnes qui doivent être indexées comme non nulles (not null)🎜🎜3. Utilisez les fonctions🎜🎜Si non utilisé Pour les index basés sur des fonctions, lors de l'utilisation de fonctions dans la clause where pour les colonnes indexées, l'optimiseur ignorera ces index. La requête suivante n'utilisera pas l'index : 🎜
select * from staff where trunc(birthdate) = &#39;01-MAY-82&#39;;
Copier après la connexion
Copier après la connexion

但是把函数应用在条件上,索引是可以生效的,把上面的语句改成下面的语句,就可以通过索引进行查找。

select * from staff where birthdate < (to_date(&#39;01-MAY-82&#39;) + 0.9999);
Copier après la connexion
Copier après la connexion

4、比较不匹配的数据类型

比较不匹配的数据类型也是难于发现的性能问题之一。下面的例子中,dept_id是一个varchar2型的字段,在这个字段上有索引,但是下面的语句会执行全表扫描。

select * from dept where dept_id = 900198;
Copier après la connexion
Copier après la connexion

这是因为oracle会自动把where子句转换成to_number(dept_id)=900198,就是3所说的情况,这样就限制了索引的使用。把SQL语句改为如下形式就可以使用索引

select * from dept where dept_id = &#39;900198&#39;;
Copier après la connexion
Copier après la connexion

5、使用like子句

使用like子句查询时,数据需要把所有的记录都遍历来进行判断,索引不能发挥作用,这种情况也要尽量避免。

Like 的字符串中第一个字符如果是‘%’则用不到索引

Column1 like ‘aaa%’ 是可以的
Column1 like ‘%aaa%’用不到
Copier après la connexion
Copier après la connexion

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…’;--才能用到索引
Copier après la connexion
Copier après la connexion

假定TEST表的dt字段是date类型的并且对dt建了索引。
如果要查‘20041010’一天的数据.下面的方法用不到索引

Select * from test where to_char(dt,’yyyymmdd’) =‘20041010’;
Copier après la connexion
Copier après la connexion

而以下将会用到索引。

select * from test where dt >=to_date(‘20041010’,’yyyymmdd’) and dt < to_date(‘20041010’,’yyyymmdd’) + 1
Copier après la connexion
Copier après la connexion

7、如果能不用到排序,则尽量避免排序。

用到排序的情况有
集合操作。Union ,minus ,intersect等,注:union all 是不排序的。

Order byGroup byDistinctIn
Copier après la connexion
Copier après la connexion

有时候也会用到排序
确实要排序的时候也尽量要排序小数据量,尽量让排序在内存中执行,有文章说,内存排序的速度是硬盘排序的1万倍。

在排序的字段上创建索引,让排序在内存中执行,加快排序速度。

8、在基于CBO的优化器(花费)下,表的统计数据过期。也可能导致不使用索引。

解决:执行表分析。获取表的最新信息。

9、获取的数据量过大,全部扫描效率更高

10、索引字段的值分散率太低,值太集中,如类型字段都是1,2, 状态类型Y-有效/N-无效。这类型的字段最好别建索引。

尽管在这些字段上建立了索引,但对全表数据区分度不大。最后还是会全表扫描。

推荐教程:《Oracle教程

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal
À propos de nous Clause de non-responsabilité Sitemap
Site Web PHP chinois:Formation PHP en ligne sur le bien-être public,Aidez les apprenants PHP à grandir rapidement!