ホームページ  >  記事  >  データベース  >  mysqlインデックスの使い方のコツと注意点を詳しく解説

mysqlインデックスの使い方のコツと注意点を詳しく解説

黄舟
黄舟オリジナル
2017-03-25 13:39:431165ブラウズ

この記事では主に mysqlindex の使用スキルと notes を紹介します。編集者が非常に優れていると考えたので、参考として共有します。エディターをフォローして一緒に見てみましょう

1. インデックスの役割

一般的なアプリケーションシステムでは、読み取りと書き込みの比率は約 10:1 であり、挿入操作や一般的な更新操作でパフォーマンスの問題が発生することはほとんどありません。最も一般的であり、問​​題を引き起こす可能性が最も高いのは、一部の複雑なクエリ操作であるため、クエリ ステートメントの最適化が最優先であることは明らかです。 データ量やアクセス量が多くない場合、mysqlのアクセスは非常に高速であり、インデックスを追加するかどうかはアクセスにほとんど影響しません。ただし、データとアクセスの量が大幅に増加すると、MySQL の速度が低下したり、場合によってはダウンしたりすることがあります。この場合、データベースの適切なインデックスを最適化することが MySQL 最適化の重要な手段であることがわかります。

インデックスの目的はクエリの効率を向上させることであり、これは辞書に例えることができます。「mysql」という単語を検索したい場合は、必ず m の文字を見つけてから、下から y の文字を見つける必要があります。最後に、残りの SQL を見つけます。索引がないと、必要な内容を見つけるためにすべての単語に目を通さなければならない場合があります。辞書以外にも、駅の時刻表や書籍のカタログなど、索引の例は身の回りのいたるところで見ることができます。それらの原理は同じです。取得したいデータの範囲を常に絞り込むことで、最終的に必要な結果を除外することができ、同時にランダムなイベントを連続したイベントに変えることができます。つまり、常に同じ検索を使用します。データをロックする方法。

インデックスを作成するときは、SQL クエリでどの列が使用されるかを考慮し、これらの列に対して 1 つ以上のインデックスを作成する必要があります。実際、インデックスは主キーまたはインデックス フィールドを保持するテーブルでもあり、各レコードが実際のテーブルを指すポインタでもあります。インデックスはデータベース ユーザーには表示されません。インデックスはクエリを高速化するためにのみ使用されます。データベース検索エンジンは、インデックスを使用してレコードを迅速に見つけます。

INSERT ステートメントと UPDATE ステートメントはインデックスのあるテーブルで実行すると時間がかかりますが、SELECT ステートメントはより速く実行されます。これは、挿入または更新が実行されると、データベースでもインデックス値を挿入または更新する必要があるためです。

2. インデックスの作成と削除 インデックスの種類:

    UNIQUE (ユニークなインデックス): 同じ値は出現できず、
  1. NULL

  2. INDEX (通常のインデックス) が存在する可能性があります。 : 同じインデックス内容の出現を許可します
  3. PROMARY KEY (主キーインデックス): 同じ値の出現を許可しません
  4. fulltext Index (全文インデックス): 値内の特定の単語を対象にすることができます、しかし効率は本当に良くありません 褒め言葉
  5. 複合インデックス: 基本的に、複数のフィールドが1つのインデックスに組み込まれ、列値の組み合わせは一意である必要があります
(1) ALTER TABLEステートメントを使用しますシンプルなテーブルを作成するには

テーブルの作成後に適用します さらに追加します。

ALTER TABLE 表名 ADD 索引类型 (unique,primary key,fulltext,index)[索引名](字段名)
//普通索引
alter table table_name add index index_name (column_list) ;
//唯一索引
alter table table_name add unique (column_list) ;
//主键索引
alter table table_name add primary key (column_list) ;

ALTER TABLE は、通常のインデックス、UNIQUE インデックス、PRIMARY KEY インデックスの 3 つのインデックス形式を作成するために使用できます。 table_name は、複数の列がある場合にインデックスに追加するテーブルの名前です。 、カンマで区切ります。インデックス名index_nameはオプションです。デフォルトでは、MySQLは最初のインデックス列に基づいて名前を割り当てます。さらに、ALTER TABLE を使用すると、単一のステートメントで複数のテーブルを変更できるため、複数のインデックスを同時に作成できます。

(2) CREATE INDEX ステートメントを使用してテーブルにインデックスを追加します

CREATE INDEX は、テーブルに通常のインデックスまたは UNIQUE インデックスを追加するために使用でき、テーブルを構築するときにインデックスを作成するために使用できます。

CREATE INDEX index_name ON table_name(username(length));

CHAR、VARCHAR 型の場合、長さはフィールドの実際の長さより小さくてもかまいませんが、BLOB および TEXT 型の場合は長さを指定する必要があります。

//create只能添加这两种索引;
CREATE INDEX index_name ON table_name (column_list)
CREATE UNIQUE INDEX index_name ON table_name (column_list)

table_name、index_name、column_list は ALTER TABLE ステートメントと同じ意味を持ち、インデックス名はオプションではありません。また、CREATE INDEX ステートメントを使用して PRIMARY KEY インデックスを作成することはできません。

(3) インデックスの削除

インデックスの削除は、ALTER TABLE または DROP INDEX ステートメントを使用して実現できます。 DROP INDEX は ALTER TABLE 内のステートメントとして処理でき、その形式は次のとおりです:

drop index index_name on table_name ;

alter table table_name drop index index_name ;

alter table table_name drop primary key ;

このうち、最初の 2 つのステートメントでは、table_name のインデックス Index_name が削除されます。最後のステートメントでは、テーブルには PRIMARY KEY インデックスを 1 つしか持てないため、PRIMARY KEY インデックスを削除するためにのみ使用されており、インデックス名を指定する必要はありません。 PRIMARY KEY インデックスが作成されていないが、テーブルに 1 つ以上の UNIQUE インデックスがある場合、MySQL は最初の UNIQUE インデックスを削除します。

テーブルから列が削除されると、インデックスが影響を受けます。複数列インデックスの場合、列の 1 つが削除されると、その列もインデックスから削除されます。インデックスを構成するすべての列を削除すると、インデックス全体が削除されます。

(4) 組み合わせインデックスとプレフィックスインデックス

在这里要指出,组合索引和前缀索引是对建立索引技巧的一种称呼,并不是索引的类型。为了更好的表述清楚,建立一个demo表如下。

create table USER_DEMO
(
  ID          int not null auto_increment comment '主键',
  LOGIN_NAME      varchar(100) not null comment '登录名',
  PASSWORD       varchar(100) not null comment '密码',
  CITY         varchar(30) not null comment '城市',
  AGE         int not null comment '年龄',
  SEX         int not null comment '性别(0:女 1:男)',
  primary key (ID)
);

为了进一步榨取mysql的效率,就可以考虑建立组合索引,即将LOGIN_NAME,CITY,AGE建到一个索引里:

代码如下:

ALTER TABLE USER_DEMO ADD INDEX name_city_age (LOGIN_NAME(16),CITY,AGE);

建表时,LOGIN_NAME长度为100,这里用16,是因为一般情况下名字的长度不会超过16,这样会加快索引查询速度,还会减少索引文件的大小,提高INSERT,UPDATE的更新速度。

如果分别给LOGIN_NAME,CITY,AGE建立单列索引,让该表有3个单列索引,查询时和组合索引的效率是大不一样的,甚至远远低于我们的组合索引。虽然此时有三个索引,但mysql只能用到其中的那个它认为似乎是最有效率的单列索引,另外两个是用不到的,也就是说还是一个全表扫描的过程。

建立这样的组合索引,就相当于分别建立如下三种组合索引:

LOGIN_NAME,CITY,AGE
LOGIN_NAME,CITY
LOGIN_NAME

为什么没有CITY,AGE等这样的组合索引呢?这是因为mysql组合索引“最左前缀”的结果。简单的理解就是只从最左边的开始组合,并不是只要包含这三列的查询都会用到该组合索引。也就是说name_city_age(LOGIN_NAME(16),CITY,AGE)从左到右进行索引,如果没有左前索引,mysql不会执行索引查询。

如果索引列长度过长,这种列索引时将会产生很大的索引文件,不便于操作,可以使用前缀索引方式进行索引,前缀索引应该控制在一个合适的点,控制在0.31黄金值即可(大于这个值就可以创建)。

SELECT COUNT(DISTINCT(LEFT(`title`,10)))/COUNT(*) FROM Arctic; -- 这个值大于0.31就可以创建前缀索引,Distinct去重复

ALTER TABLE `user` ADD INDEX `uname`(title(10)); -- 增加前缀索引SQL,将人名的索引建立在10,这样可以减少索引文件大小,加快索引查询速度

三.索引的使用及注意事项   

EXPLAIN可以帮助开发人员分析SQL问题,explain显示了mysql如何使用索引来处理select语句以及连接表,可以帮助选择更好的索引和写出更优化的查询语句。

使用方法,在select语句前加上Explain就可以了:

Explain select * from user where id=1;

尽量避免这些不走索引的sql:

SELECT `sname` FROM `stu` WHERE `age`+10=30;-- 不会使用索引,因为所有索引列参与了计算

SELECT `sname` FROM `stu` WHERE LEFT(`date`,4) <1990; -- 不会使用索引,因为使用了函数运算,原理与上面相同

SELECT * FROM `houdunwang` WHERE `uname` LIKE&#39;后盾%&#39; -- 走索引

SELECT * FROM `houdunwang` WHERE `uname` LIKE "%后盾%" -- 不走索引

-- 正则表达式不使用索引,这应该很好理解,所以为什么在SQL中很难看到regexp关键字的原因

-- 字符串与数字比较不使用索引;
CREATE TABLE `a` (`a` char(10));
EXPLAIN SELECT * FROM `a` WHERE `a`="1" -- 走索引
EXPLAIN SELECT * FROM `a` WHERE `a`=1 -- 不走索引

select * from dept where dname=&#39;xxx&#39; or loc=&#39;xx&#39; or deptno=45 
--如果条件中有or,即使其中有条件带索引也不会使用。换言之,就是要求使用的所有字段,都必须建立索引, 我们建议大家尽量避免使用or 关键字

-- 如果mysql估计使用全表扫描要比使用索引快,则不使用索引

索引虽然好处很多,但过多的使用索引可能带来相反的问题,索引也是有缺点的:

  1. 虽然索引大大提高了查询速度,同时却会降低更新表的速度,如对表进行INSERT,UPDATE和DELETE。因为更新表时,mysql不仅要保存数据,还要保存一下索引文件

  2. 建立索引会占用磁盘空间的索引文件。一般情况这个问题不太严重,但如果你在要给大表上建了多种组合索引,索引文件会膨胀很宽

索引只是提高效率的一个方式,如果mysql有大数据量的表,就要花时间研究建立最优的索引,或优化查询语句。

使用索引时,有一些技巧:

1.索引不会包含有NULL的列

只要列中包含有NULL值,都将不会被包含在索引中,复合索引中只要有一列含有NULL值,那么这一列对于此符合索引就是无效的。

 2.使用短索引

对串列进行索引,如果可以就应该指定一个前缀长度。例如,如果有一个char(255)的列,如果在前10个或20个字符内,多数值是唯一的,那么就不要对整个列进行索引。短索引不仅可以提高查询速度而且可以节省磁盘空间和I/O操作。

3.索引列排序

mysql查询只使用一个索引,因此如果where子句中已经使用了索引的话,那么order by中的列是不会使用索引的。因此数据库默认排序可以符合要求的情况下不要使用排序操作,尽量不要包含多个列的排序,如果需要最好给这些列建复合索引。

4.like语句操作

一般情况下不鼓励使用like操作,如果非使用不可,注意正确的使用方式。like ‘%aaa%'不会使用索引,而like ‘aaa%'可以使用索引。

5.不要在列上进行运算

6.不使用NOT IN 、a8093152e673feb7aba1828c43532094、!=操作,但211df07dbe7fea6e188a5b56353eb306,>=,BETWEEN,IN是可以用到索引的

7.索引要建立在经常进行select操作的字段上。

这是因为,如果这些列很少用到,那么有无索引并不能明显改变查询速度。相反,由于增加了索引,反而降低了系统的维护速度和增大了空间需求。

8.索引要建立在值比较唯一的字段上。

9.对于那些定义为text、image和bit数据类型的列不应该增加索引。因为这些列的数据量要么相当大,要么取值很少。

10.在where和join中出现的列需要建立索引。

11. where のクエリ条件に不等号 (where 列 != ...) がある場合、mysql はインデックスを使用できません。

12. where 句のクエリ条件で関数が使用されている場合 (where DAY (column) =... など)、mysql はインデックスを使用できません。

13. 結合操作 (複数のデータテーブルからデータを抽出する必要がある場合) では、mysql は主キーと外部キーのデータ型が同じ場合にのみインデックスを使用できます。それ以外の場合、インデックスは使用されません。それは時間の中で確立されます。

以上がmysqlインデックスの使い方のコツと注意点を詳しく解説の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。