ホームページ データベース mysql チュートリアル 高パフォーマンスSQLの書き方

高パフォーマンスSQLの書き方

May 09, 2019 am 09:34 AM
mysql

まず第一に、実行計画とは何なのかを理解する必要があります。

実行プランは、SQL ステートメントと関連テーブルの統計情報に基づいてデータベースによって作成されるクエリ プランです。このプランはクエリ オプティマイザによって自動的に分析されます。たとえば、SQL ステートメントが100,000 レコードを抽出する テーブル内の 1 つのレコードを検索するために、クエリ オプティマイザーは「インデックス検索」方法を選択します。テーブルがアーカイブされ、5,000 レコードしか残っていない場合、クエリ オプティマイザーは計画を変更し、「フル テーブル スキャン」を使用します。 " "方法。

実行計画は固定されたものではなく、「個別化」されていることがわかります。正しい「実行計画」を生成するには、次の 2 つの重要なポイントがあります。

SQL ステートメントは、クエリ オプティマイザーに何をしたいのかを明確に伝えていますか?

クエリ オプティマイザーによって取得されたデータベース統計は最新かつ正確ですか?

推奨コース: MySQL チュートリアル

高パフォーマンスSQLの書き方

#SQL ステートメントの統一された記述方法

次の 2 つの SQL ステートメントについて、プログラマはそれらが同じデータベース クエリ オプティマイザーであると考えます。それは違うと思ってください。

select*from dual 
select*From dual
ログイン後にコピー
実際には、ケースは異なります。クエリ アナライザーは、これを 2 つの異なる SQL ステートメントとみなして、2 回解析する必要があります。 2 つの実行プランを生成します。したがって、プログラマは、同じクエリ ステートメントがどこでも一貫していることを確認する必要があります。スペースが 1 つ多くても機能しません。

SQL 文はあまり複雑に書かないでください

データベースから取得した SQL 文が A4 用紙 2 枚に印刷されるのをよく見かけます。さよなら。一般的に、このような複雑なステートメントには通常問題が発生します。この 2 ページにわたる SQL ステートメントを元の作成者に問い合わせましたが、時間がかかりすぎてしばらく理解できないと言われました。オリジナルの作成者ですら SQL ステートメントに混乱する可能性があり、データベースも同様に混乱することが考えられます。


一般に、Select ステートメントの結果はサブセットとして使用され、そのサブセットからクエリが実行されます。この種の 1 レベルのネストされたステートメントは比較的一般的ですが、経験によれば、 3 レベルを超えるネストされたステートメントは許可されません。設定すると、クエリ オプティマイザーは簡単に間違った実行プランを与える可能性があります。唖然としたからだ。人工知能のようなものは最終的には人間の解像度に劣り、人間がめまいを感じれば、データベースもめまいを感じることは保証できます。


また、実行計画は再利用可能であり、SQL文が単純であればあるほど再利用できる可能性が高くなります。複雑な SQL ステートメントで 1 文字が変更されると、その文字を再解析する必要があり、大量のゴミがメモリに詰め込まれることになります。データベースがどれほど非効率になるかは考えられます。


「一時テーブル」を使用して中間結果を一時的に保存する

SQL ステートメントを簡素化する重要な方法は、一時テーブルを使用して中間結果を一時的に保存することです。ただし、一時テーブルの利点はこれらをはるかに超えています。一時的な結果は一時テーブルに一時的に保存され、後続のクエリは tempdb に保存されます。これにより、プログラム内のメイン テーブルの複数回のスキャンが回避され、「」も大幅に削減されます。 「共有ロック」により、プログラム実行中にブロックされます。「更新ロック」により、ブロックが軽減され、同時実行パフォーマンスが向上します。


OLTP システム SQL ステートメントはバインド変数を使用する必要があります


select*from orderheader where changetime >'2010-10-20 00:00:01' 
select*from orderheader where changetime >'2010-09-22 00:00:01'
ログイン後にコピー
クエリ オプティマイザーは、上記の 2 つのステートメントを異なる SQL ステートメントと見なし、2 回解析する必要があります。バインド変数

select*from orderheader where changetime >@chgtime
ログイン後にコピー
@chgtime 変数を使用すると、任意の値を渡すことができるため、多数の同様のクエリで実行プランを再利用でき、SQL ステートメントを解析する負担を大幅に軽減できます。データベース。データベースの効率を向上させるには、一度解析して複数回再利用することが原則です。

バインド変数ピーク

すべてのものには 2 つの側面があり、バインド変数はほとんどの OLTP 処理に適用できますが、例外もあります。たとえば、where 条件のフィールドが「スキューフィールド」である場合です。


「傾斜フィールド」は、列内の値のほとんどが同じであることを意味します。たとえば、国勢調査フォームの「民族」列では、90% 以上が漢民族です。したがって、SQL ステートメントで 30 歳の漢民族の人口をクエリする場合は、「ethnic」列を where 条件に配置する必要があります。このとき、バインド変数 @nation を使用すると大きな問題が発生します。


@nation によって渡された最初の値が「Han」の場合、実行プラン全体で必然的にテーブル スキャンが選択されることを想像してください。次に、渡される 2 番目の値は「Buyi」ですが、「Buyi」の割合は 1 万分の 1 しかない可能性があるため、インデックス検索を使用する必要があるのは当然です。ただし、最初に解析された「Han」の実行プランは再利用されるため、2回目でもテーブルスキャン方式が使用されます。この問題は有名な「バインド変数スヌーピング」です。「スキューフィールド」にはバインド変数を使用しないことをお勧めします。

begin tran は必要な場合にのみ使用してください

SQL Server の SQL ステートメントは既定ではトランザクションであり、ステートメントの実行後に既定でコミットされます。実際、これは begin tran の最小化された形式であり、begin tran が各ステートメントの先頭に暗黙的に示され、commit が最後に暗黙的に示されるのと同じです。

場合によっては、begin tran を明示的に宣言する必要があります。たとえば、「挿入、削除、および変更」操作を実行する場合、複数のテーブルを同時に変更する必要があります。複数のテーブルのすべての変更を行う必要があります。テーブルが成功したか、どのテーブルも成功しませんでした。 begin tran はそのような役割を果たし、複数の SQL ステートメントをまとめて実行し、最終的にそれらをまとめてコミットできます。利点はデータの一貫性が保証されていることですが、完璧なものはありません。 Begin tran によって支払われる代償として、送信前に、SQL ステートメントによってロックされているすべてのリソースは、コミットされるまで解放できなくなります。

Begin tran がトラップする SQL ステートメントが多すぎると、データベースのパフォーマンスが低下することがわかります。大規模なトランザクションがコミットされる前に、他のステートメントが必然的にブロックされ、その結果、大量のブロックが発生します。

Begin tran を使用する原則は、データの一貫性を確保することを前提として、begin tran によってトラップされる SQL ステートメントが少ないほど良いということです。場合によっては、トリガーを使用してデータを同期できますが、begin tran は必ずしも使用されるわけではありません。

一部の SQL クエリ ステートメントは nolock を追加する必要があります

SQL ステートメントに nolock を追加することは、SQL Server の同時パフォーマンスを向上させる重要な手段です。これは必須ではありません。 Oracle では、Oracle の構造がより合理的であり、「前のデータ」を保存するための UNDO テーブルスペースがあるためです。変更中にデータがコミットされていない場合、読み取られるのは変更前のコピーです。コピーは UNDO 表スペースに配置されます。このように、Oracle の読み取りと書き込みは互いに独立できるため、Oracle は広く賞賛されています。 SQL Server の読み取りと書き込みは相互にブロックされます。同時実行パフォーマンスを向上させるために、一部のクエリに nolock を追加して、読み取り中に書き込みを許可できます。ただし、欠点は、コミットされていないダーティ データが読み取られる可能性があることです。 nolock を使用するには 3 つの原則があります。

(1) クエリ結果を「挿入、削除、変更」に使用する場合、nolock は追加できません。

(2) クエリされたテーブルはページ分割が頻繁に発生するテーブルであるため、nolock の使用には注意してください。

(3) 一時テーブルを使用すると、Oracle の UNDO テーブルスペースと同様の機能を持つ「データのフォアシャドウ」を保存することもできます。 nolock は使用しないでください。

クラスタード インデックスはテーブルのシーケンス フィールドに基づいて構築されていないため、テーブルがページ分割される傾向があります。

たとえば、順序テーブルには次のようなものがあります。注文番号 orderid と顧客番号 contactid の場合、どのフィールドにクラスター化インデックスを追加する必要がありますか?このテーブルでは順序番号が順番に追加されており、orderid にクラスター化インデックスを追加すると、最後に新しい行が追加されるため、ページ分割が頻繁に発生しません。ただし、ほとんどのクエリは顧客 ID に基づいているため、contactid にクラスター化インデックスを追加することのみが意味があります。注文テーブルの場合、contactid は連続フィールドではありません。

たとえば、「Zhang San」の「contactid」が 001 である場合、「Zhang San」の注文情報はこのテーブルの最初のデータ ページに配置する必要があります。今日注文する 注文の場合、注文情報は表の最後のページには配置できず、最初のページに配置されます。最初のページが埋まっている場合はどうなりますか?申し訳ありませんが、このレコード用のスペースを確保するには、このテーブル内のすべてのデータを元に戻す必要があります。

SQL Server のインデックスは Oracle のインデックスとは異なります。SQL Server のクラスター化インデックスは、実際にはクラスター化インデックス フィールドの順序でテーブルを並べ替えます。これは、Oracle のインデックス構成テーブルと同等です。 SQL Server のクラスター化インデックスはテーブルそのものを組織化したものであるため、効率が非常に高くなります。このため、レコードを挿入する際、レコードの位置はランダムに配置されるのではなく、データ ページ上の本来配置されるべき位置に配置され、そのデータ ページにスペースがない場合、ページ分割が発生します。したがって、明らかに、クラスター化インデックスはテーブルの順次フィールドに基づいて構築されていないため、テーブルはページ分割が発生しやすくなります。

私はかつて、特定のテーブルのインデックスを再作成した後、友人の挿入効率が大幅に低下する状況に遭遇しました。おそらくこのような状況であると推測されます。テーブルのクラスター化インデックスは、テーブルの順次フィールドに基づいて構築されていない可能性があります。テーブルはアーカイブされることが多いため、テーブルのデータは疎な状態で存在します。たとえば、Zhang San は 20 件の注文を出しましたが、過去 3 か月間の注文は 5 件のみです。アーカイブ戦略では、3 か月分のデータを保持します。すると、Zhang San の過去 15 件の注文がアーカイブされ、15 個の欠員が残ります。挿入に入力されます。発生したときに再利用されます。この場合、空き領域があるため、ページ分割は発生しません。ただし、クエリではデータのない空のスペースをスキャンする必要があるため、クエリのパフォーマンスは比較的低くなります。

クラスター化インデックスの再構築後は状況が変わりました。クラスター化インデックスの再構築はテーブル内のデータの再配置を意味するためです。元の空席はなくなり、ページの充填率は非常に高くなります。データを挿入するときは、ページ分割が頻繁に発生するため、パフォーマンスが大幅に低下します。

クラスター化インデックスがシーケンシャル フィールドに構築されていないテーブルの場合、ページ フィル レートを比較的低く設定する必要がありますか?クラスター化インデックスの再構築を回避しますか?それは検討する価値のある質問です!

nolock を追加した後、ページ分割が頻繁に発生するテーブルにクエリを実行すると、読み取りのスキップや繰り返しが発生しやすくなる可能性があります

加nolock后可以在“插、删、改”的同时进行查询,但是由于同时发生“插、删、改”,在某些情况下,一旦该数据页满了,那么页分裂不可避免,而此时nolock的查询正在发生,比如在第100页已经读过的记录,可能会因为页分裂而分到第101页,这有可能使得nolock查询在读101页时重复读到该条数据,产生“重复读”。同理,如果在100页上的数据还没被读到就分到99页去了,那nolock查询有可能会漏过该记录,产生“跳读”。

上面提到的哥们,在加了nolock后一些操作出现报错,估计有可能因为nolock查询产生了重复读,2条相同的记录去插入别的表,当然会发生主键冲突。

使用like进行模糊查询时应注意

有的时候会需要进行一些模糊查询比如

select*from contact where username like ‘%yue%’
ログイン後にコピー

关键词%yue%,由于yue前面用到了“%”,因此该查询必然走全表扫描,除非必要,否则不要在关键词前加%,

数据类型的隐式转换对查询效率的影响

sql server2000的数据库,我们的程序在提交sql语句的时候,没有使用强类型提交这个字段的值,由sql server 2000自动转换数据类型,会导致传入的参数与主键字段类型不一致,这个时候sql server 2000可能就会使用全表扫描。Sql2005上没有发现这种问题,但是还是应该注意一下。

以上が高パフォーマンスSQLの書き方の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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)

MySQL:簡単な学習のためのシンプルな概念 MySQL:簡単な学習のためのシンプルな概念 Apr 10, 2025 am 09:29 AM

MySQLは、オープンソースのリレーショナルデータベース管理システムです。 1)データベースとテーブルの作成:createdatabaseおよびcreateTableコマンドを使用します。 2)基本操作:挿入、更新、削除、選択。 3)高度な操作:参加、サブクエリ、トランザクション処理。 4)デバッグスキル:構文、データ型、およびアクセス許可を確認します。 5)最適化の提案:インデックスを使用し、選択*を避け、トランザクションを使用します。

phpmyadminを開く方法 phpmyadminを開く方法 Apr 10, 2025 pm 10:51 PM

次の手順でphpmyadminを開くことができます。1。ウェブサイトコントロールパネルにログインします。 2。phpmyadminアイコンを見つけてクリックします。 3。MySQL資格情報を入力します。 4.「ログイン」をクリックします。

MySQL:世界で最も人気のあるデータベースの紹介 MySQL:世界で最も人気のあるデータベースの紹介 Apr 12, 2025 am 12:18 AM

MySQLはオープンソースのリレーショナルデータベース管理システムであり、主にデータを迅速かつ確実に保存および取得するために使用されます。その実用的な原則には、クライアントリクエスト、クエリ解像度、クエリの実行、返品結果が含まれます。使用法の例には、テーブルの作成、データの挿入とクエリ、および参加操作などの高度な機能が含まれます。一般的なエラーには、SQL構文、データ型、およびアクセス許可、および最適化の提案には、インデックスの使用、最適化されたクエリ、およびテーブルの分割が含まれます。

なぜMySQLを使用するのですか?利点と利点 なぜMySQLを使用するのですか?利点と利点 Apr 12, 2025 am 12:17 AM

MySQLは、そのパフォーマンス、信頼性、使いやすさ、コミュニティサポートに選択されています。 1.MYSQLは、複数のデータ型と高度なクエリ操作をサポートし、効率的なデータストレージおよび検索機能を提供します。 2.クライアントサーバーアーキテクチャと複数のストレージエンジンを採用して、トランザクションとクエリの最適化をサポートします。 3.使いやすく、さまざまなオペレーティングシステムとプログラミング言語をサポートしています。 4.強力なコミュニティサポートを提供し、豊富なリソースとソリューションを提供します。

単一のスレッドレディスの使用方法 単一のスレッドレディスの使用方法 Apr 10, 2025 pm 07:12 PM

Redisは、単一のスレッドアーキテクチャを使用して、高性能、シンプルさ、一貫性を提供します。 I/Oマルチプレックス、イベントループ、ノンブロッキングI/O、共有メモリを使用して同時性を向上させますが、並行性の制限、単一の障害、および書き込み集約型のワークロードには適していません。

MySQLおよびSQL:開発者にとって不可欠なスキル MySQLおよびSQL:開発者にとって不可欠なスキル Apr 10, 2025 am 09:30 AM

MySQLとSQLは、開発者にとって不可欠なスキルです。 1.MYSQLはオープンソースのリレーショナルデータベース管理システムであり、SQLはデータベースの管理と操作に使用される標準言語です。 2.MYSQLは、効率的なデータストレージと検索機能を介して複数のストレージエンジンをサポートし、SQLは簡単なステートメントを通じて複雑なデータ操作を完了します。 3.使用の例には、条件によるフィルタリングやソートなどの基本的なクエリと高度なクエリが含まれます。 4.一般的なエラーには、SQLステートメントをチェックして説明コマンドを使用することで最適化できる構文エラーとパフォーマンスの問題が含まれます。 5.パフォーマンス最適化手法には、インデックスの使用、フルテーブルスキャンの回避、参加操作の最適化、コードの読み取り可能性の向上が含まれます。

MySQLの場所:データベースとプログラミング MySQLの場所:データベースとプログラミング Apr 13, 2025 am 12:18 AM

データベースとプログラミングにおけるMySQLの位置は非常に重要です。これは、さまざまなアプリケーションシナリオで広く使用されているオープンソースのリレーショナルデータベース管理システムです。 1)MySQLは、効率的なデータストレージ、組織、および検索機能を提供し、Web、モバイル、およびエンタープライズレベルのシステムをサポートします。 2)クライアントサーバーアーキテクチャを使用し、複数のストレージエンジンとインデックスの最適化をサポートします。 3)基本的な使用には、テーブルの作成とデータの挿入が含まれ、高度な使用法にはマルチテーブル結合と複雑なクエリが含まれます。 4)SQL構文エラーやパフォーマンスの問題などのよくある質問は、説明コマンドとスロークエリログを介してデバッグできます。 5)パフォーマンス最適化方法には、インデックスの合理的な使用、最適化されたクエリ、およびキャッシュの使用が含まれます。ベストプラクティスには、トランザクションと準備された星の使用が含まれます

Redis ExporterサービスでRedis Dropletを監視します Redis ExporterサービスでRedis Dropletを監視します Apr 10, 2025 pm 01:36 PM

Redisデータベースの効果的な監視は、最適なパフォーマンスを維持し、潜在的なボトルネックを特定し、システム全体の信頼性を確保するために重要です。 Redis Exporter Serviceは、Prometheusを使用してRedisデータベースを監視するために設計された強力なユーティリティです。 このチュートリアルでは、Redis Exporterサービスの完全なセットアップと構成をガイドし、監視ソリューションをシームレスに構築します。このチュートリアルを研究することにより、完全に動作する監視設定を実現します

See all articles