MySQL ビッグデータ クエリ最適化エクスペリエンスの共有 (推奨)

MySQL ビッグデータ クエリ最適化エクスペリエンスの共有 (推奨)

本格的な MySQL 最適化!

MySQL のデータ量が少ない場合は最適化は不要です。データ量が多い場合は最適化が不可欠です。クエリが最適化されていない場合は 10 秒かかります。適切に最適化されている場合は、同じクエリに 10 ミリ秒かかります。

これは何と痛い認識でしょう!

プログラマーの用語で言うと、MySQL の最適化とは、インデックスの最適化と where 条件の最適化を意味します。

実験環境: MacBook Pro MJLQ2CH/A、MySQL 5.7、データ量: 212万以上

1つ:

 記事から*を選択
 内部結合(
 選択ID
 記事より
 どこ
  長さ(content_url) > 0 かつ
  (id = article.source_idのソースからステータスを選択)=1 かつ
  (id = article.category_idのカテゴリからステータスを選択) = 1 かつ
  ステータス = 1 かつ ID < 2164931
 スティック降順、pub_time降順で並び替え
 制限 240,15
 ) として
USING(id);

一見すると、上司は間違いなく私を殺したいと思うでしょう。なぜ自己関連付けや内部結合を行う必要があるのでしょうか? XX 階の皆さん、肉切り包丁を持ってきてください。ブロガーを殺したいんです! ! !

正直に言うと、朝出かけるときに頭がドアに押し付けられることはなかったので、そんなことは起きてほしくなかったのです。

1. データ量が多い場合は、大きなオフセットでページング クエリを実行する必要があります。これにより、クエリの速度が大幅に向上します。その理由は、結合サブテーブルで ID を使用してテーブル全体をカバーし、完全なテーブル スキャンを回避するためです。

私の order by を見てください (ささやく: これは単なる order by です。誰が書けるでしょうか)。この order by をフィールド desc に置き換えるか、独自のテーブルで説明して、何が起こるかを確認してください。追加 ---> filesort ! くそっ !

2. 複数の条件を持つこのような order by の場合、通常は 2 つのフィールドにそれぞれインデックスを直接追加しますが、Extra ---> filesort も使用します。別のアプローチとして、order by の後のすべての条件に結合インデックスを追加します。順序は order by の順序と一致している必要があることに注意してください。こうすれば、Extra に残されたのはどこなのかだけです。

where,(select status from source where id = article.source_id)=1 and ...これはなんと奇妙な書き方でしょう!

3. join+index方式を検討しましたが、試してみたところ、この方式とほぼ同じであることがわかりました。本番環境はこのように書かれているので、そのままにしておきましょう。また、2 つのインデックス (source_id、category_id) を保存できます。怠惰を止めることは誰にもできません。将来損失が発生した場合は、戻って最適化を続けることができます。

4. 昨晩、この点に気付きました。where 条件を満たす順序は、右から左の順に、最後の条件を最初に満たすというものです。テストのためにインデックスを削除したところ、確かに効果があり、時間が 6 秒から 4 秒に短縮されました。インデックスを最適化した後、再度テストしたところ、順序による時間消費への影響は 0.X ミリ秒とほとんど無視できることがわかりました。

二:

 記事から*を選択
 内部結合(
 SELECT id FROM article WHERE INSTR(ifnull(title,''),'战狼') > 0 かつ status != 9
 pub_time 降順で並び替え
 制限 100,10

 ) は t として扱われます (id);

うーん――また内部結合か……。

INSTR(ifnull(title,''),'Wolf Warrior') > 0 のように使用しないのはなぜでしょうか......

1. 管理プラットフォームでの検索であるため、検索エンジンで検索されていません。検索エンジンは 1 時間に 1 回しかデータを同期しないため、データが不完全です。検索する場合、管理者は必要な結果のみを気にします。たとえば、%XX% はインデックスを使用できず、効率は instr の 5 倍低くなります。また、正規表現 '.*XX*.' もテストしましたが、それでも instr よりも少し時間がかかります。つまり...

desc または explain、filesort.....pub_time にインデックスを追加して動作するかどうか確認するか、filesort...

2. この状況には別の解決策があり、 SELECT id FROM article force index(pub_time)てこのインデックスの使用を指定します。しかし、この書き方は柔軟性に欠けるので、やめましょう。 Baidu で検索したところ、ある人からアドバイスをもらいました。ステータスと pub_time の結合インデックス (pub_time_status、先頭に順序条件) を作成し、where クエリを実行するときにこのインデックスを自動的に強制します。

三つ:

status != 9 の場合に article から * を選択し、 pub_time で並べ替え、 desc limit 100000,25 を指定します。
desc または explain、または filesort..... 以前に status と pub_time の共同インデックスを作成しませんでしたか? 理由を教えてください...

まあ、私もわかりません。status と pub_time の別の結合インデックスstatus_pub_timeを作成します。今回は where 条件が前にあり、explain に filesort はありませんが、このインデックスは使用されませんpub_time_statusをフックします。理解できない

同時に、TWO の SQL についても説明しました。これは次のようになります。

これら 2 つのうちいずれか 1 つを削除しても機能しません。 いずれか 1 つを削除すると、SQL はファイル ソートを実行します。

4:

フォローから*を選択
 ここで、(((SELECT status FROM source WHERE id=follow.source_id)=1 and follow.type=1) または ((select status from topic WHERE id=follow.source_id)=1 and follow.type=2)) AND user_id=10054
 ORDER BY ソート制限 15,15;
 SELECT * from follow inner join(
 フォローからIDを選択
 ここで、(((SELECT status FROM source WHERE id=follow.source_id)=1 and follow.type=1) または ((select status from topic WHERE id=follow.source_id)=1 and follow.type=2)) AND user_id=10054
 ORDER BY ソート制限 15,15
 ) を t として使用します (id);
 (SELECT id、source_id、user_id、temporary、sort、follow_time、read_time、type from follow where (SELECT status FROM source WHERE id=follow.source_id)=1 and follow.type=1 and user_id=10054)
 すべて結合
 (SELECT id、source_id、user_id、temporary、sort、follow_time、read_time、type from follow where (select status from topic WHERE id=follow.source_id)=1 and follow.type=2 and user_id=10054) を実行します。
 ORDER BY ソート制限 15,15;

これら 3 つの SQL ステートメントを見てください。興味深いですね。

公平を期すために、インデックス user_id_sort(user_id,sort) を最適化し、where が user_id を使用してこのインデックスを強制するようにしました。

最初の文: 0.48ms

2番目の文: 0.42ms

3 番目の文: 6 ミリ秒。時間がかかる理由は、結合 (テーブルを 2 回クエリしてサブテーブルにマージする) の後、インデックスを使用して order by の並べ替えをカバーできないためです。

場合によっては、union が or よりも必ずしも高速であるとは限りません。

要約する

上記は、編集者が共有したMySQLビッグデータクエリ最適化の経験です。皆様のお役に立てれば幸いです。ご質問がある場合は、メッセージを残してください。編集者がすぐに返信します。また、123WORDPRESS.COM ウェブサイトをサポートしてくださっている皆様にも感謝申し上げます。

以下もご興味があるかもしれません:
  • MySQLとPHPの基礎と応用: データクエリ
  • MySQLデータクエリが多すぎるとOOMが発生するかどうかについての簡単な議論
  • MySQLデータベースの数千万件のデータクエリとストレージの詳細な説明
  • MySQL 集計統計データの低速クエリの最適化
  • MySQL json 形式のデータクエリ操作
  • MySQL と PHP の基礎と応用: データクエリステートメント

<<:  Nginx ログのカスタマイズとログ バッファの有効化の詳細な説明

>>:  koa2 サービスに SSL を設定する方法

推薦する

MySQLクエリは、フィールドが数値とカンマではないことを指定します。

コアSQL文数字を含まない MySQL クエリ ステートメント: SELECT * FROM tes...

njs モジュールを使用して nginx 構成に js スクリプトを導入する

目次序文1. NJSモジュールをインストールする方法1: NJSモジュールを動的にロードする方法2:...

CSS を使用して 3 列のアダプティブ レイアウト (両側は固定幅、中央はアダプティブ) を実現します。

いわゆる 3 列適応レイアウトとは、両側の幅が固定され、中央のブロックの幅が適応されることを意味しま...

MySQL トランザクション分離レベルの原則例分析

導入あなたも面接でこれに遭遇したことがあるはずです。トランザクションの分離レベルについてお話ししまし...

Javascript Bootstrapのグリッドシステム、ナビゲーションバー、カルーセルの詳細な説明

目次ブートストラップと関連コンテンツの紹介グリッドシステムネストされた列列オフセット列の並べ替えナビ...

Linux システムで tcpdump を使用してパケットをキャプチャする方法

まずサンプルコードを見てみましょう: 1. 共通パラメータ tcpdump -i eth0 -nn ...

Centos8環境でSSHポート番号を変更する方法

目次序文始める序文サーバーのデフォルトの SSH ポート番号は通常 22 であるため、ほとんどのユー...

Linux での MySQL のアンインストールとインストールのグラフィック チュートリアル

ブログを書くのは初めてです。開発に携わって2年になります。仕事の後に何か有意義なことを見つけたいと思...

JavaScriptのスリープ関数の使用

目次1.スリープ機能2.タイムアウトを設定する3. 約束4. 非同期待機5. 1秒後に出力1、2秒後...

CentOS7環境にMySQL5.5データベースをインストールする

目次1. 現在のシステムにMySQLがインストールされているかどうかを確認する2. インストールされ...

Ubuntu 20.04にvncserverをインストールする方法

Ubuntu 20.04は2020年4月に正式にリリースされました。本日、ミラーシステムを正式にイン...

Linux での sshd サービスとサービス管理コマンドの詳細な説明

sshd SSH は Secure Shell の略で、アプリケーション層のセキュリティ プロトコル...

LinuxにMySQLをインストールするための詳細なチュートリアル

すべてのプラットフォーム用の MySQL ダウンロードは、MySQL ダウンロードから入手できます。...

Ubuntu 18.04 システムでの Redis および phpredis 拡張機能のインストールと設定の詳細な説明

この記事では、Ubuntu 18.04 に Redis と phpredis 拡張機能をインストール...

MySQLデータクエリが多すぎるとOOMが発生するかどうかについての簡単な議論

目次サーバー層でのフルテーブルスキャンの影響InnoDB におけるフルテーブルスキャンの影響Inno...