ホームページ データベース mysql チュートリアル PHP 動的 Web サイト MySQL インデックス分析と最適化を高速化します。

PHP 動的 Web サイト MySQL インデックス分析と最適化を高速化します。

Dec 13, 2016 pm 05:08 PM

この記事では主に、MySQL インデックス分析と動的 Web サイトの最適化を高速化する方法について説明します。

1. インデックスとは何ですか?

インデックスは、特定の値を持つレコードをすばやく検索するために使用されます。すべての MySQL インデックスは B ツリーの形式で保存されます。インデックスがない場合、クエリを実行するときに、MySQL は要件を満たすレコードが見つかるまで、テーブル全体のすべてのレコードを最初のレコードからスキャンする必要があります。テーブル内のレコードの数が増えるほど、この操作のコストも高くなります。検索条件として使用されるカラムにインデックスが作成されている場合、MySQL はレコードをスキャンすることなく、目的のレコードの位置を迅速に取得できます。テーブルに 1000 レコードがある場合、インデックスを使用してレコードを検索すると、レコードを順次スキャンするよりも少なくとも 100 倍高速になります。

people という名前のテーブルを作成するとします。

CREATE TABLE people ( peopleid SMALLINT NOT NULL, name CHAR(50) NOT NULL );
ログイン後にコピー

次に、1000 個の異なる名前の値を people テーブルに完全にランダムに挿入します。データ ファイル内では、名前列には明示的な順序がありません。 name カラムにインデックスを作成すると、MySQL はインデックス内の name カラムをソートし、インデックス内の各項目に対して、データ ファイル内の実際のレコードの場所への「ポインタ」を内部的に保存します。したがって、名前が「Mike」に等しいレコードの peopleid を見つけたい場合 (SQL コマンドは「SELECT peopleid FROM people WHERE name='Mike';」)、MySQL は「Mike」を検索できます。 name のインデックスの値を入力し、直接データ ファイルの対応する行に移動すると、その行の peopleid (999) が正確に返されます。このプロセス中、MySQL は 1 行を処理するだけで結果を返します。 「name」列にインデックスがない場合、MySQL はデータ ファイル内のすべてのレコード、つまり 1,000 レコードをスキャンします。明らかに、MySQL が処理する必要があるレコードの数が少ないほど、タスクをより速く完了できます。

2. インデックスの種類

MySQL は、選択できるさまざまなインデックス タイプを提供します:

通常のインデックス:

これは最も基本的なインデックス タイプであり、一意性などの制限はありません。通常のインデックスは次の方法で作成できます:

CREATE INDEX <インデックスの名前> ON tablename (列のリスト) などのインデックスを作成します。

ALTER TABLE tablename ADD INDEX [name of ] のようにテーブルを変更します。インデックス] (列のリスト);

テーブル作成時にインデックスを指定します。例: CREATE TABLE tablename ([...], INDEX [インデックス名] (列のリスト));

一意のインデックス:

この種のインデックスと前述の「通常のインデックス」は基本的に同じですが、1 つの違いがあります。インデックス列のすべての値は 1 回だけ出現でき、一意である必要があります。一意のインデックスは次の方法で作成できます:

CREATE UNIQUE INDEX <インデックスの名前> ON tablename (列のリスト) などのインデックスを作成します。

ALTER TABLE tablename ADD UNIQUE [name] のようにテーブルを変更します。 of Index] ] (列のリスト);

CREATE TABLE tablename ([...], UNIQUE [インデックス名] (列のリスト));

主キー: など、テーブルを作成するときにインデックスを指定します。

主キーはUniqueインデックスですが、「PRIMARY KEY」として指定する必要があります。 AUTO_INCREMENT 型の列を扱ったことがある場合は、主キーなどの概念にすでに精通しているかもしれません。主キーは通常、テーブルの作成時に「CREATE TABLE テーブル名 ([...], PRIMARY KEY (列のリスト));」のように指定します。ただし、「ALTER TABLE tablename ADD PRIMARY KEY (list of columns);」のようにテーブルを変更して主キーを追加することもできます。各テーブルは主キーを 1 つだけ持つことができます。

全文インデックス:

MySQL は、バージョン 3.23.23 以降、全文インデックス作成と全文検索をサポートします。 MySQL では、フルテキスト インデックスのインデックス タイプは FULLTEXT です。フルテキスト インデックスは、VARCHAR 型または TEXT 型の列に作成できます。これは、CREATE TABLE コマンド、または ALTER TABLE または CREATE INDEX コマンドによって作成できます。大規模なデータ セットの場合、ALTER TABLE (または CREATE INDEX) コマンドを使用してフルテキスト インデックスを作成する方が、フルテキスト インデックスを使用して空のテーブルにレコードを挿入するよりも高速です。この記事の以下の説明では、フルテキスト インデックスについては説明しません。詳細については、MySQL のドキュメントを参照してください。

3. 単一列インデックスと複数列インデックス

インデックスは単一列インデックスまたは複数列インデックスにすることができます。以下では、具体的な例を使用して、これら 2 つのインデックスの違いを説明します。このような people テーブルがあるとします。

CREATE TABLE people ( peopleid 
SMALLINT NOT NULL AUTO_INCREMENT,
firstname CHAR(50) NOT NULL, lastname CHAR(50) NOT NULL, 
age SMALLINT NOT NULL,
townid SMALLINT NOT NULL, PRIMARY KEY (peopleid) );
ログイン後にコピー

以下は、この people テーブルに挿入するデータです:

このデータ フラグメントには、「Mikes」という名前の 4 人の人物がいます (そのうちの 2 人はサリバンズ、2 人はマコネルズです)。 2人は17歳で、もう1人はジョー・スミスという珍しい名前だった。

このテーブルの主な目的は、指定されたユーザーの姓、名、年齢に基づいて、対応する peopleid を返すことです。たとえば、名前が Mike Sullivan で年齢が 17 歳のユーザーの peopleid を検索する必要がある場合があります (SQL コマンドは SELECT peopleid FROM people WHERE firstname='Mike' AND lastname='Sullivan' AND age=17 です) ;)。クエリが実行されるたびに MySQL がテーブル全体をスキャンすることを望まないため、ここではインデックスを考慮する必要があります。

首先,我们可以考虑在单个列上创建索引,比如firstname、lastname或者age列。如果我们创建firstname列的索引(ALTER TABLE people ADD INDEX firstname (firstname);),MySQL将通过这个索引迅速把搜索范围限制到那些firstname='Mike'的记录,然后再在这个“中间结果集”上进行其他条件的搜索:它首先排除那些lastname不等于“Sullivan”的记录,然后排除那些age不等于17的记录。当记录满足所有搜索条件之后,MySQL就返回最终的搜索结果。

由于建立了firstname列的索引,与执行表的完全扫描相比,MySQL的效率提高了很多,但我们要求MySQL扫描的记录数量仍旧远远超过了实际所需要的。虽然我们可以删除firstname列上的索引,再创建lastname或者age列的索引,但总地看来,不论在哪个列上创建索引搜索效率仍旧相似。

为了提高搜索效率,我们需要考虑运用多列索引。如果为firstname、lastname和age这三个列创建一个多列索引,MySQL只需一次检索就能够找出正确的结果!下面是创建这个多列索引的SQL命令:

ALTER TABLE people ADD INDEX fname_lname_age (firstname,lastname,age);
ログイン後にコピー

由于索引文件以B-树格式保存,MySQL能够立即转到合适的firstname,然后再转到合适的lastname,最后转到合适的age。在没有扫描数据文件任何一个记录的情况下,MySQL就正确地找出了搜索的目标记录!

那么,如果在firstname、lastname、age这三个列上分别创建单列索引,效果是否和创建一个firstname、lastname、age的多列索引一样呢?答案是否定的,两者完全不同。当我们执行查询的时候,MySQL只能使用一个索引。如果你有三个单列的索引,MySQL会试图选择一个限制最严格的索引。但是,即使是限制最严格的单列索引,它的限制能力也肯定远远低于firstname、lastname、age这三个列上的多列索引。

四、最左前缀

多列索引还有另外一个优点,它通过称为最左前缀(Leftmost Prefixing)的概念体现出来。继续考虑前面的例子,现在我们有一个firstname、lastname、age列上的多列索引,我们称这个索引为fname_lname_age。当搜索条件是以下各种列的组合时,MySQL将使用fname_lname_age索引:

firstname,lastname,age
firstname,lastname
firstname
ログイン後にコピー

从另一方面理解,它相当于我们创建了(firstname,lastname,age)、(firstname,lastname)以及(firstname)这些列组合上的索引。下面这些查询都能够使用这个fname_lname_age索引:

SELECT peopleid FROM people 
WHERE firstname=&#39;Mike&#39; AND lastname=&#39;Sullivan&#39; AND age=&#39;17&#39;; 
SELECT peopleid FROM people WHERE firstname=&#39;Mike&#39; AND lastname=&#39;Sullivan&#39;; 
SELECT peopleid FROM people WHERE firstname=&#39;Mike&#39;; 
The following queries cannot use the index at all: 
SELECT peopleid FROM people WHERE lastname=&#39;Sullivan&#39;; 
SELECT peopleid FROM people WHERE age=&#39;17&#39;; 
SELECT peopleid FROM people WHERE lastname=&#39;Sullivan&#39; AND age=&#39;17&#39;;
ログイン後にコピー

五、选择索引列

在性能优化过程中,选择在哪些列上创建索引是最重要的步骤之一。可以考虑使用索引的主要有两种类型的列:在WHERE子句中出现的列,在join子句中出现的列。请看下面这个查询:

SELECT age ## 不使用索引
FROM people WHERE firstname='Mike' ## 考虑使用索引
AND lastname='Sullivan' ## 考虑使用索引

这个查询与前面的查询略有不同,但仍属于简单查询。由于age是在SELECT部分被引用,MySQL不会用它来限制列选择操作。因此,对于这个查询来说,创建age列的索引没有什么必要。下面是一个更复杂的例子:

SELECT people.age, ##不使用索引
town.name ##不使用索引
FROM people LEFT JOIN town ON
people.townid=town.townid ##考虑使用索引
WHERE firstname='Mike' ##考虑使用索引
AND lastname='Sullivan' ##考虑使用索引

与前面的例子一样,由于firstname和lastname出现在WHERE子句中,因此这两个列仍旧有创建索引的必要。除此之外,由于town表的townid列出现在join子句中,因此我们需要考虑创建该列的索引。那么,我们是否可以简单地认为应该索引WHERE子句和join子句中出现的每一个列呢?差不多如此,但并不完全。我们还必须考虑到对列进行比较的操作符类型。MySQL只有对以下操作符才使用索引:<,<=,=,>,>=,BETWEEN,IN,以及某些时候的LIKE。可以在LIKE操作中使用索引的情形是指另一个操作数不是以通配符(%或者_)开头的情形。例如,“SELECT peopleid FROM people WHERE firstname LIKE 'Mich%';”这个查询将使用索引,但“SELECT peopleid FROM people WHERE firstname LIKE '%ike';”这个查询不会使用索引。

以上内容就是加速PHP动态网站 MySQL索引分析和优化,希望可以帮助到大家,想要更多相关内容请关注PHP中文网(www.php.cn)!

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

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHPのビッグデータ構造処理スキル PHPのビッグデータ構造処理スキル May 08, 2024 am 10:24 AM

ビッグ データ構造の処理スキル: チャンキング: データ セットを分割してチャンクに処理し、メモリ消費を削減します。ジェネレーター: データ セット全体をロードせずにデータ項目を 1 つずつ生成します。無制限のデータ セットに適しています。ストリーミング: ファイルやクエリ結果を 1 行ずつ読み取ります。大きなファイルやリモート データに適しています。外部ストレージ: 非常に大規模なデータ セットの場合は、データをデータベースまたは NoSQL に保存します。

PHP で MySQL クエリのパフォーマンスを最適化するにはどうすればよいですか? PHP で MySQL クエリのパフォーマンスを最適化するにはどうすればよいですか? Jun 03, 2024 pm 08:11 PM

MySQL クエリのパフォーマンスは、検索時間を線形の複雑さから対数の複雑さまで短縮するインデックスを構築することで最適化できます。 PreparedStatement を使用して SQL インジェクションを防止し、クエリのパフォーマンスを向上させます。クエリ結果を制限し、サーバーによって処理されるデータ量を削減します。適切な結合タイプの使用、インデックスの作成、サブクエリの使用の検討など、結合クエリを最適化します。クエリを分析してボトルネックを特定し、キャッシュを使用してデータベースの負荷を軽減し、オーバーヘッドを最小限に抑えます。

PHP で MySQL のバックアップと復元を使用するにはどうすればよいですか? PHP で MySQL のバックアップと復元を使用するにはどうすればよいですか? Jun 03, 2024 pm 12:19 PM

PHP で MySQL データベースをバックアップおよび復元するには、次の手順を実行します。 データベースをバックアップします。 mysqldump コマンドを使用して、データベースを SQL ファイルにダンプします。データベースの復元: mysql コマンドを使用して、SQL ファイルからデータベースを復元します。

PHP を使用して MySQL テーブルにデータを挿入するにはどうすればよいですか? PHP を使用して MySQL テーブルにデータを挿入するにはどうすればよいですか? Jun 02, 2024 pm 02:26 PM

MySQLテーブルにデータを挿入するにはどうすればよいですか?データベースに接続する: mysqli を使用してデータベースへの接続を確立します。 SQL クエリを準備します。挿入する列と値を指定する INSERT ステートメントを作成します。クエリの実行: query() メソッドを使用して挿入クエリを実行します。成功すると、確認メッセージが出力されます。

MySQL 8.4 で mysql_native_password がロードされていないエラーを修正する方法 MySQL 8.4 で mysql_native_password がロードされていないエラーを修正する方法 Dec 09, 2024 am 11:42 AM

MySQL 8.4 (2024 年時点の最新の LTS リリース) で導入された主な変更の 1 つは、「MySQL Native Password」プラグインがデフォルトで有効ではなくなったことです。さらに、MySQL 9.0 ではこのプラグインが完全に削除されています。 この変更は PHP および他のアプリに影響します

PHP で MySQL ストアド プロシージャを使用するにはどうすればよいですか? PHP で MySQL ストアド プロシージャを使用するにはどうすればよいですか? Jun 02, 2024 pm 02:13 PM

PHP で MySQL ストアド プロシージャを使用するには: PDO または MySQLi 拡張機能を使用して、MySQL データベースに接続します。ストアド プロシージャを呼び出すステートメントを準備します。ストアド プロシージャを実行します。結果セットを処理します (ストアド プロシージャが結果を返す場合)。データベース接続を閉じます。

PHP を使用して MySQL テーブルを作成するにはどうすればよいですか? PHP を使用して MySQL テーブルを作成するにはどうすればよいですか? Jun 04, 2024 pm 01:57 PM

PHP を使用して MySQL テーブルを作成するには、次の手順が必要です。 データベースに接続します。データベースが存在しない場合は作成します。データベースを選択します。テーブルを作成します。クエリを実行します。接続を閉じます。

Oracleデータベースとmysqlの違い Oracleデータベースとmysqlの違い May 10, 2024 am 01:54 AM

Oracle データベースと MySQL はどちらもリレーショナル モデルに基づいたデータベースですが、Oracle は互換性、スケーラビリティ、データ型、セキュリティの点で優れており、MySQL は速度と柔軟性に重点を置いており、小規模から中規模のデータ セットに適しています。 ① Oracle は幅広いデータ型を提供し、② 高度なセキュリティ機能を提供し、③ エンタープライズレベルのアプリケーションに適しています。① MySQL は NoSQL データ型をサポートし、② セキュリティ対策が少なく、③ 小規模から中規模のアプリケーションに適しています。

See all articles