常識の照合-mysqlインデックス

データベース設計で考慮すべき問題

ここに画像の説明を挿入します

インデックスを使用する理由

  1. データをすばやくクエリする

インデックスデータ構造

  1. 二分探索のための二分探索木を構築する
  2. 検索用のBTree構造を確立します
  3. 検索するB +ツリー構造を確立する
  4. 検索用のハッシュ構造を確立する

BTree

  1. ルートノードには、少なくとも2つの子が含まれます
  2. ツリーの各ノードには、最大m個の子が含まれます
  3. ルートノードとリーフノードを除いて、他のすべてのノードには少なくともceil(m / 2)の子があります
  4. すべてのリーフノードは同じレイヤー上にあります
    ここに画像の説明を挿入します

B +ツリー

  1. 非リーフノードのサブツリーポインタの数は、キーワードの数と同じです。
  2. 非リーフノードのサブツリーポインタp [i]は、キー値[k [i]、k [i + 1])のサブツリーを指します。
  3. 非リーフノードはインデックス作成にのみ使用され、データはリーフノードに保存されます
  4. すべてのリーフノードには、次のリーフノードを指すチェーンポインタがあります
    ここに画像の説明を挿入します

B + Treeはストレージインデックスに適しています

  1. B +ツリーのディスク読み取りおよび書き込みコストは低くなります(データはリーフノードにのみ保存されるため、ディスクIOを削減できます)
  2. B +ツリークエリの効率はより安定しています
  3. B +ツリーは、データベースのスキャンに役立ちます

ハッシュインデックス

クエリ速度は理論的にはB + Treeよりも高速です。
短所:

  1. 会うためだけに=in範囲クエリを使用することません
  2. データの並べ替え操作を回避するために使用することはできません
  3. インデックスキーの一部を使用してクエリを実行することはできません
  4. 多数のハッシュ衝突が発生したため、パフォーマンスは必ずしもBTreeよりも高いとは限りません。

密インデックスと疎インデックスの違い

密なインデックスリーフノードは、キー値だけでなく、同じ行の他の列の情報も保存します。密なインデックスは、テーブルの物理的な並べ替え順序も決定します。テーブルは1つの物理ソート順しか持てないため、テーブルは1つの密なインデックスしか持てません
スパースインデックスリーフノードはキー情報とプライマリキー情報のみを保存し、データはプライマリキーインデックスを介してクエリする必要があります。

InnoDB

  1. 主キーが定義されている場合、主キーは密なインデックスとして使用されます
  2. 主キーが定義されていない場合、テーブルの最初の一意の空でないインデックスが密なインデックスとして使用されます
  3. 上記の条件が満たされない場合、Innodbは非表示の主キー(密なインデックスを生成します
  4. 非主キーインデックスは、2つのルックアップを含む、関連するキービットとそれに対応する主キー値を格納します
    InnoDBデンスインデックス図
    MyISAMスパースインデックス図

遅いクエリSQLを見つけて最適化する方法

  1. 遅いログに基づいて遅いクエリSQLを見つけます
  2. Explainおよびその他のツールを使用してSQLを分析する
  3. SQLを変更するか、SQLにインデックスを取得させてみてください

遅いログに関連する構成情報を照会します(mysql 8.0.xに基づく)

SHOW VARIABLES LIKE '%query%'

結果は以下のとおりです。

Variable_name                 Value                                            
----------------------------  -------------------------------------------------
binlog_rows_query_log_events  OFF                                              
ft_query_expansion_limit      20                                               
have_query_cache              NO                                               
long_query_time               1.000000                                         
query_alloc_block_size        8192                                             
query_prealloc_size           8192                                             
slow_query_log                ON                                               
slow_query_log_file           /var/lib/mysql/izwz99rnmfr0cdntpgsfr9z-slow.log  

slow_query_logONは、低速ログがオンになっていることを意味します。
slow_query_log_file低速ログファイルパスは、
long_query_time低速SQLと見なされる期間をマイクロ秒(us)で意味します。1.000000us= 1s

スロークエリログをオンにします
。slow_query_logがオフの場合、スローログはオンになりません。次のように開くことができます。

SET GLOBAL slow_query_log = ON

遅いクエリの場合、変更には時間がかかると見なされます

SET GLOBAL long_query_time = 1; #单位1s
SET GLOBAL long_query_time = 0.8; #单位0.8s = 800ms

変更後、クライアントは再接続して有効にし、変更された結果を表示する必要があります。mysqlの再起動後、デフォルト値が復元されます。mysql構成ファイルを変更することで永続的に有効にできます

カウントされた遅いクエリの数をクエリする

SHOW STATUS LIKE '%slow_queries%'

現在の接続の遅いクエリの数を表示するだけで、再接続すると0に戻ります

mysqlサーバーで遅いログファイルを表示する

# Time: 2021-02-22T13:39:46.688722Z
# User@Host: root[root] @  [139.226.12.65]  Id:   201
# Query_time: 1.006213  Lock_time: 0.195229 Rows_sent: 0  Rows_examined: 0
use lwl_registry;
SET timestamp=1614001185;
select * from order_info where pwd = '122'

Query_timeは、このクエリに時間がかかります

explainSQLステートメントを分析することによって

Explainを通じて、SQLがインデックスを使用したかどうかを確認できます

EXPLAIN SELECT * FROM order_info WHERE username = '122'

結果は以下のとおりです。

    id  select_type  table       partitions  type    possible_keys  key     key_len  ref       rows  filtered  Extra        
------  -----------  ----------  ----------  ------  -------------  ------  -------  ------  ------  --------  -------------
     1  SIMPLE       order_info  (NULL)      ALL     (NULL)         (NULL)  (NULL)   (NULL)  360772     10.00  Using where  

type:、ソート・パフォーマンス・データ行を見つける方法それ降順に順位を:
system> const> eq_ref> ref> fulltext> ref_or_null> index_merge> unique_subquery> index_subquery> range> index>all

indexそして、allこのクエリが全表スキャンを実行していることを表します。遅いクエリのEXPLAINステートメントがこれら2つの値の結果である場合は、最適化を検討する必要があります。

Extra:次の2つの項目の値が表示される場合は、mysqlがインデックスをまったく使用していないことを意味し、最適化を検討する必要があります

追加の価値 説明
filesortの使用 MySQLは、メモリ内またはディスク上で並べ替えられる可能性のあるインデックスに従ってテーブルから関連するコンテンツを順番に読み取るのではなく、外部インデックスを使用して結果を並べ替えることを意味します。
MySQLのインデックスを使用して実行できない並べ替え操作は、ファイルの並べ替えと呼ばれます
一時的な使用 mysqがクエリ結果を並べ替えるときに一時テーブルを使用することを示します。order byクエリの並べ替えとグループ化で一般的に使用されgroup byます。

一般的な最適化ソリューション:

  1. ビジネスで許可されている場合は、既存のインデックスフィールドを使用してクエリを実行できます。
  2. インデックスを適切に追加する
    alter table order_info add index idx_name(username)
    
  3. インデックスフィールドで並べ替え
  4. 概要インデックス
    MySQLのインデックスは、以下の演算子のためにのみ使用し<<==>=between andlike 非%开头インデックスを使用し、in行かないかもしれないインデックスを取るかもしれないが、!=各テーブルには16個のインデックスを作成することができ、理論的には、インデックスを取ることはありません。
  5. MySQLは、「允许null isnull 列也加上索引,但只会对」のクエリ条件で有効になります

質問:InnoDBのテーブルにidプライマリキーインデックスがあり、空ではない一意のインデックスsessionIdがある場合、count(id)でデータ項目の数をカウントするときに使用されるインデックスフィールドはどれですか?

EXPLAIN SELECT COUNT(id) FROM `client`

回答:ではない一意のインデックスsessionIdが使用され、結果は次のようになります。
ここに画像の説明を挿入します
理由: InnoDBの主キーで使用されるクラスター化インデックスであるリーフノードに他の列が含まれているため、クエリオプティマイザーが最適なインデックスを選択します。データ、あなたはもっと読む必要がありますデータ。sessionIdは空ではなく、非クラスター化インデックスであり、インデックスフィールドと主キーのみが含まれ、データ量が少なく、読み取りが高速です。

インデックスの取得を強制
ここに画像の説明を挿入します
where条件がある場合、条件内のインデックスが使用されます

SELECT COUNT(id) FROM `client` WHERE id = 39  #走主键索引
SELECT COUNT(id) FROM `client` WHERE session_id = 1427325133344736216 #走唯一索引

ジョイント(結合)インデックスの左端の一致原理の理由

  1. コンポジットインデックス、左端の費用収益対応の原則それが範囲クエリを(遭遇するまで、MySQLは常に右側に照合されます>、、 、試合を停止します。たとえば、複合インデックス(a、b、c、d)クエリ条件が使用されている場合、インデックスはdに使用されません。<betweenlikewhere a=3 and b=4 and c>5 and d = 6
  2. =またin、たとえば、where a=3 and c=5 and b=4クエリシーケンスabcが条件ではない場合でも、クエリの組み合わせインデックス(a、b、c)が故障している可能性がありますが、クエリオプティマイザの最適化後、インデックスは実行できますがwhere c=5 and b=4、左端を満たしてません。一致、インデックスを取得できません

左端の一致原則の理由: 2番目のフィールドの並べ替えは最初のフィールドに基づいているため、2番目のフィールドだけでは順序が狂っています。

できるだけ多くのインデックスを作成する方が良いですか?

  1. データ量が少ないテーブルにはインデックスを付ける必要がなく、インデックスを付けると追加のインデックスオーバーヘッドが増加します
  2. データの変更はインデックスを維持する必要があるため、インデックスが多いほどメンテナンスコストが高くなります
  3. より多くのインデックスは、多くのスペースが必要であることを意味します

おすすめ

転載: blog.csdn.net/u013202238/article/details/113934806