ホームページ 見出し データベース コードによるデータベースのロックを防ぐために SQL クエリを高速化するためのヒント

データベース コードによるデータベースのロックを防ぐために SQL クエリを高速化するためのヒント

Mar 09, 2018 am 09:15 AM
秘密 防ぐ

データベース コードによるデータベースのロックを防ぐために SQL クエリを高速化するためのヒント

データベース分野はまだ比較的未成熟であるため、SQL 開発者はあらゆるプラットフォームで苦労し、同じ間違いを繰り返しています。もちろん、データベース ベンダーはある程度の進歩を遂げており、引き続き大きな問題に取り組み続けています。

SQL 開発者が SQL Server、Oracle、DB2、Sybase、MySQL、またはその他のリレーショナル データベース プラットフォームでコードを作成しているかどうかに関係なく、同時実行性、リソース管理、スペース管理、実行速度が依然として彼らを悩ませています。

問題の 1 つは、ほぼすべてのベスト プラクティスに対して、少なくとも 1 つの例外を指摘できる特効薬がないことです。

データベースのチューニングは芸術でもあり科学でもあると言いますが、全体に適用される厳格なルールはほとんどないので、これは当然のことです。あるシステムで解決した問題は別のシステムでは問題になりませんし、その逆も同様です。

クエリのチューニングに関しては正しい答えはありませんが、だからといって諦める必要はありません。次の原則のいくつかに従うことで、素晴らしい結果が得られることが期待できます。

CASE の代わりに UPDATE を使用しないでください

この問題は非常に一般的ですが、UPDATE を使用するのが自然で論理的であると思われるため、多くの開発者はこの問題を無視することがよくあります。

次のシナリオを例に挙げます。一時テーブルにデータを挿入し、別の値が存在する場合は、特定の値を表示する必要があります。

おそらく、Customer テーブルからレコードを抽出し、注文金額が 100,000 ドルを超える顧客を「優先」としてマークしたいと考えます。

そこで、テーブルにデータを挿入し、UPDATE ステートメントを実行し、注文金額が 100,000 ドルを超える顧客の CustomerRank 列を「Preferred」に設定します。

問題は、UPDATE ステートメントがログに記録されることです。つまり、テーブルに書き込まれるたびに 2 回書き込まれます。

解決策: SQL クエリでインライン CASE ステートメントを使用します。これにより、各行の注文金額条件がチェックされ、テーブルに書き込まれる前に「優先」タグが設定されます。これにより、処理パフォーマンスが大幅に向上します。

コードをやみくもに再利用しないでください

この問題も非常に一般的であり、必要なデータを取得できることがわかっているため、他の人が書いたコードをコピーするのは簡単です。

問題は、必要のないデータを取得しすぎることが多く、開発者がそれを合理化することがほとんどないため、結果的に大量のデータが発生することです。

これは通常、WHERE 句内の追加の外部結合または追加の条件として現れます。再利用されたコードを正確な要件に合わせて合理化すると、パフォーマンスを大幅に向上させることができます。

必要な数の列を抽出します

この質問は質問 2 と似ていますが、列に固有のものです。列を 1 つずつリストする代わりに、SELECT* を使用してすべてのクエリをコーディングするのが簡単です。

問題は、必要のないデータが抽出されすぎることです。私はこの間違いを何度も見てきました。開発者は、数百万行を含む 120 列のテーブルに対して SELECT* クエリを実行しますが、使用する列は 3 つまたは 5 つだけです。

つまり、実際に必要なデータよりもはるかに多くのデータを扱っていることになり、クエリが結果を返すのは奇跡です。必要のないデータを大量に処理するだけでなく、他のプロセスからリソースを奪うことになります。

クエリを 2 回 (ダブルディップ) しないでください

これも多くの人が犯す間違いです。それは、数億行のテーブルからデータを抽出するストアド プロシージャを作成することです。

開発者は、カリフォルニアに住んでおり、年間 40,000 ドル以上を稼ぐ顧客に関する情報を抽出したいと考えていました。そこで、カリフォルニアに住む顧客にクエリを実行し、クエリ結果を一時テーブルに格納します。

次に、年収が 40,000 ドルを超える顧客をクエリし、それらの結果を別の一時テーブルに入れます。最後に、2 つのテーブルを結合して最終結果を取得します。

冗談ですか?これは 1 回のクエリで実行する必要があります。代わりに、非常に大きなテーブルに対して 2 回クエリを実行します。愚かなことはしないでください。大きなテーブルに対して 1 回だけクエリを実行してみると、ストアド プロシージャの実行がはるかに高速になることがわかります。

少し異なるシナリオは、プロセスのいくつかのステップで大きなテーブルのサブセットが必要となり、その結果、大きなテーブルが毎回クエリされることになる場合です。

この問題を回避するには、このサブセットをクエリして別の場所に永続化し、後続のステップをこの小さなデータ セットに指示します。

一時テーブルをいつ使用するかを理解する

この問題は解決するのが少し面倒ですが、その効果は大きいです。一時テーブルは、大きなテーブルが 2 回クエリされるのを防ぐなど、さまざまな状況で使用できます。一時テーブルを使用すると、大規模なテーブルの結合に必要な処理能力を大幅に削減することもできます。

テーブルを大きなテーブルに接続する必要があり、大きなテーブルに条件がある場合は、大きなテーブルのデータの必要な部分を一時テーブルに抽出し、その一時テーブルに接続するだけで、次のことができます。クエリのパフォーマンスを向上させます。

これは、同じテーブルに対して同様の結合を実行する必要があるストアド プロシージャ内に複数のクエリがある場合にも役立ちます。

前段階データ

これは、見落とされがちな古い手法であるため、私が話したいお気に入りのトピックの 1 つです。

大きなテーブルに対して同様の結合操作を実行するレポートまたはストアド プロシージャ (またはそのグループ) がある場合、事前にテーブルを結合してテーブルに永続化することでデータを事前にステージングすると、非常に役立ちます。

これで、この事前ステージング テーブルに対してレポートを実行できるようになり、大規模な結合が回避されます。この方法は常に使用できるわけではありませんが、一度使用すると、サーバー リソースを節約する優れた方法であることがわかります。

注意: 多くの開発者は、結合条件を何度も入力する必要がないように、クエリ自体に焦点を当て、結合に基づいて読み取り専用ビューを作成することで、この結合の問題を回避しています。

しかし、このアプローチの問題は、クエリを必要とするすべてのレポートに対してクエリを実行する必要があることです。データを事前にステージングすると、接続を 1 回実行するだけで済み (レポートの 10 分前など)、他のユーザーは大規模な接続を回避できます。

私がこのトリックをどれほど気に入っているかはわかりませんが、ほとんどの環境では、一般的に使用されるテーブルの一部が常に接続されているため、それらを最初に事前ステージングできない理由はありません。

バッチ削除と更新

これも見落とされがちなヒントですが、大規模なテーブルから大量のデータを削除または更新することは、正しく行わないと悪夢のような作業になる可能性があります。

問題は、両方のステートメントが単一のトランザクションとして実行されることです。トランザクションを終了する必要がある場合、またはトランザクションの実行中にシステムで問題が発生した場合、システムはトランザクション全体をロールバックする必要があり、これには長い時間がかかります。

これらの操作はその間、他のトランザクションもブロックするため、実際にはシステムにボトルネックが生じます。解決策は、小さなバッチで削除または更新することです。

これにより、いくつかの方法で問題が解決されます。

トランザクションが終了する理由に関係なく、ロールバックする必要がある行の数が少ないため、データベースははるかに速くオンラインに戻ります。

小さなバッチトランザクションがディスクにコミットされると、他のトランザクションが一部の作業を処理するために入ることができるため、同時実行性が大幅に向上します。

同様に、多くの開発者は、これらの削除操作と更新操作は同じ日に完了する必要があると頑固に信じてきました。これは、特にアーカイブを行っている場合には必ずしも当てはまりません。

操作を延長する必要がある場合は、拡張することができます。これらの集中的な操作の実行に時間がかかる場合は、小さなバッチを使用することでこれを実現できます。システムの速度を低下させないでください。

カーソルのパフォーマンスを向上させるために一時テーブルを使用します

可能であればカーソルを使用しないことが最善です。カーソルには速度の問題があり、それ自体が多くの操作にとって大きな問題となるだけでなく、操作が他の操作を長時間ブロックする原因となり、システムの同時実行性が大幅に低下する可能性があります。

ただし、カーソルの使用を常に回避できるわけではありません。カーソルの使用が避けられない場合は、代わりに一時テーブルに対してカーソル操作を実行して、カーソルによって引き起こされるパフォーマンスの問題を取り除くことができます。

たとえば、テーブルを検索し、いくつかの比較結果に基づいて複数の列のカーソルを更新します。そのデータを一時テーブルに入れて、アクティブなテーブルではなく一時テーブルと比較できる場合があります。

その後、はるかに小さく、ロック時間が短いアクティブ テーブルに対して 1 つの UPDATE ステートメントを実行できます。

このようなデータ変更を実行すると、同時実行性が大幅に向上します。最後に、カーソルを使用する必要はまったくなく、コレクションベースのソリューションが常に存在することを言っておきます。

テーブル値関数の使用

これは、専門家だけが知っている一種の秘密であるため、私が常にお気に入りのテクニックの 1 つです。

クエリの SELECT リストでスカラー関数を使用すると、結果セットの行ごとに関数が呼び出されるため、大規模なクエリのパフォーマンスが大幅に低下する可能性があります。

ただし、スカラー関数をテーブル値関数に変換し、クエリで CROSS APPLY を使用すると、パフォーマンスが大幅に向上します。

同じバッチで多くのテーブルに対して大規模な操作を実行しないでください

これは明白に思えるかもしれませんが、そうではありません。要点をよりよく説明するため、別の鮮やかな例を使用します。

多くのブロックが発生し、多くの操作が停止しているシステムがあります。 1 日に数回実行される削除ルーチンが、明示的なトランザクションで 14 のテーブルからデータを削除していたことが判明しました。 1 つのトランザクションで 14 個のテーブルすべてを処理するということは、すべての削除が完了するまで各テーブルをロックすることを意味します。

解決策は、各テーブルの削除を個別のトランザクションに分割し、各削除トランザクションが 1 つのテーブルのみをロックするようにすることです。

これにより、他のテーブルが解放され、ブロックが緩和され、他の操作の実行が継続できるようになります。ブロックを防ぐために、このような大規模なトランザクションを常に個別の小さなトランザクションに分割する必要があります。

トリガーを使用しないでください

これは前のものとほとんど同じですが、それでも言及する価値があります。トリガーの問題: トリガーで実行したいことはすべて、元の操作と同じトランザクションで実行されます。

Orders テーブルの行を更新中に別のテーブルにデータを挿入するトリガーを作成した場合、トリガーが完了するまで両方のテーブルがロックされます。

更新後に別のテーブルにデータを挿入する必要がある場合は、更新と挿入をストアド プロシージャに入れて、別のトランザクションで実行します。

ロールバックする必要がある場合は、両方のテーブルを同時にロックする必要がなく、簡単にロールバックできます。いつものように、トランザクションは短くし、一度に複数のリソースをロックしないでください。

GUID でクラスター化しないでください

何年も経った今でも、まだこの問題と格闘していることが信じられません。しかし、私は今でも少なくとも年に 2 回はクラスター化された GUID に遭遇します。

GUID (Globally Unique Identifier) は、ランダムに生成された 16 バイトの数値です。この列でテーブル内のデータを並べ替えると、DATE や IDENTITY などの着実に増加する値を使用するよりもはるかに速くテーブルの断片化が発生します。

私は数年前に、クラスター化された GUID を持つテーブルに大量のデータを挿入し、IDENTITY 列を持つ別のテーブルに同じデータを挿入するベンチマークを実行しました。

GUID テーブルは非常に断片化されており、わずか 15 分後にパフォーマンスが数千パーセント低下しました。

5 時間後、IDENTITY テーブルのパフォーマンスは数パーセント低下しただけであり、これは GUID にだけ適用されるのではなく、あらゆる揮発性列に適用されます。

データが存在するかどうかを確認したいだけの場合は、行をカウントしないでください

この状況は非常に一般的です。テーブルにデータが存在することを確認する必要があり、この確認の結果に基づいて、次のことが必要です。特定の操作を実行します。

データが存在するかどうかを確認するために SELECT COUNT(*) FROMdbo.T1 を実行している人をよく見かけます。 @ct> 0

存在する場合 (dbo.T1 から 1 を選択)
  1. BEGIN
  2. END
  3. テーブル内のすべてをカウントするのではなく、最初の行を取得するだけです探す。 SQL Server は EXISTS を正しく使用できるほど賢く、2 番目のコードは非常に高速に結果を返します。
  4. テーブルが大きくなるほど、この点の違いがより明確になります。データが大きくなりすぎる前に、適切な対処を行ってください。データベースを調整するのに早すぎるということはありません。

    私は実際に、運用データベースの 1 つで、2 億 7,000 万行のテーブルに対してこの例を実行しました。
  5. 最初のクエリには 15 秒かかり、456,197 件の論理読み取りが含まれていました。2 番目のクエリは 1 秒未満で結果を返し、含まれる論理読み取りは 5 件のみでした。

    ただし、本当にテーブルの行をカウントする必要があり、テーブルが大きい場合は、システム テーブルから抽出する別の方法もあります。
SELECT rows fromsysindexes を使用すると、すべてのインデックスの行数が取得されます。

そして、クラスター化インデックスはデータ自体を表すため、WHERE indid = 1 を追加してテーブルの行を取得し、テーブル名を含めるだけです。
  1. したがって、最後のクエリは次のとおりです:

    1.SELECT rows from sysindexes where object_name(id)='T1'andindexid =1
  2. 2 億 7,000 万行のテーブルでは、結果は 1 秒以内に返されます, 論理読み取りが 6 回だけなので、パフォーマンスが異なります。

  3. 逆方向検索を実行しないでください
  4. 単純なクエリ SELECT * FROMCustomers WHERE RegionalID を例として挙げます。このクエリはテーブル スキャンを利用した行ごとの比較を必要とする逆検索であるため、このクエリではインデックスを使用できません。このようなタスクを実行する必要がある場合は、インデックスを使用するようにクエリを書き直すとパフォーマンスが大幅に向上する場合があります。

  5. クエリは次のように簡単に書き直すことができます:
  6. 1.SELECT * FROM Customers WHERE RegionalID

このクエリはインデックスを使用するため、データセットが大きい場合は、そのパフォーマンスはテーブル スキャン バージョンよりもはるかに優れています。

もちろん、それほど簡単なことはなく、パフォーマンスが悪化する可能性があるため、使用する前に試してください。非常に多くの要因が関係していますが、100% 機能します。

最後に、このクエリはルール 4 に違反していることに気付きました。クエリを 2 回実行しないでください。しかし、これは厳密なルールがないことも示しています。ここでは 2 回クエリを実行していますが、コストのかかるテーブル スキャンを避けるためにこれを実行しています。

これらのヒントをすべて常に使用できるわけではありませんが、心に留めておけば、いつか大きな問題を解決するために使用できるでしょう。

覚えておくべき最も重要なことは、私の言うことを独断として受け取らないでください。実際の環境で試してみてください。同じ解決策がすべてのケースで機能するわけではありませんが、パフォーマンス低下のトラブルシューティングに私がいつも使用しているものであり、常に機能します。

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

Pip ミラー ソース分析: Python パッケージのインストールを高速化するためのヒント Pip ミラー ソース分析: Python パッケージのインストールを高速化するためのヒント Jan 16, 2024 am 08:27 AM

Pip Mirror Source を 1 つの記事で理解する: Python パッケージのインストール速度を向上させる秘密 Python は、データ分析、人工知能、その他の分野で広く使用されているプログラミング言語です。その柔軟で包括的なサードパーティ ライブラリにより、Python は開発者にとっての最初の選択肢です。しかし、これらのサードパーティライブラリをインストールする場合、ネットワーク環境の制限によりインストール速度が遅くなることが多く、開発効率の大きな障害となっています。この問題を解決するには、Pip ミラー ソースを使用して Python パッケージのインストール速度を向上させます。とは

PHP8 の基礎となる開発原則の分析: サーバーのパフォーマンスを向上させる秘密 PHP8 の基礎となる開発原則の分析: サーバーのパフォーマンスを向上させる秘密 Sep 10, 2023 pm 08:34 PM

PHP はサーバーサイド開発で広く使用されているスクリプト言語であり、インターネット業界で重要な位置を占めています。 PHP8 のリリースにより、基礎となる開発原則がより多くの人々の注目を集めるようになりました。この記事では、PHP8 の基礎となる開発原則を分析し、サーバーのパフォーマンスを向上させる方法の秘密を探ります。まず、PHP8 の重要な機能をいくつか見てみましょう。 PHP8 では、PHP 言語に基づいて多くの最適化と改善が行われています。最も顕著な機能は、ジャストインタイム (JIT) コンパイラーの導入です。

DDoS 攻撃を防ぐ方法: Linux サーバーを保護する DDoS 攻撃を防ぐ方法: Linux サーバーを保護する Sep 09, 2023 pm 02:15 PM

DDoS 攻撃を防ぐ方法: Linux サーバーを保護する DDoS 攻撃は、サーバーが過負荷になったり使用不能になったりする一般的なサイバーセキュリティの脅威です。この記事では、ネットワーク構成の最適化、ファイアウォールの使用、DDoS 保護ソフトウェアのインストールなど、Linux サーバーを DDoS 攻撃から保護するいくつかの方法を紹介します。ネットワーク構成の最適化 ネットワーク構成の最適化は、サーバーが大量のトラフィックに耐えられるようにするための最初のステップです。以下に、構成の最適化に関する重要な提案をいくつか示します。 サーバーの帯域幅を増やします。

PHP を使用して登録攻撃を防ぐにはどうすればよいですか? PHP を使用して登録攻撃を防ぐにはどうすればよいですか? Aug 19, 2023 pm 10:08 PM

PHP を使用して登録攻撃を防ぐにはどうすればよいですか?インターネットの発展に伴い、登録機能はほぼすべての Web サイトに必要な機能の 1 つになりました。しかし、悪意のある分子もこの機会を利用して登録攻撃を実行し、大量の偽アカウントを悪意を持って登録し、Web サイトに多くの問題を引き起こしました。レジストレーション ブラシ攻撃を防ぐために、いくつかの効果的な技術的手段を使用できます。この記事では、PHP プログラミング言語を使用して登録攻撃を防ぐ方法を紹介し、対応するコード例を示します。 1. IP アドレス制限登録攻撃は通常、同じ IP アドレスから行われるため、

C++ 開発で null ポインター例外を防ぐ方法 C++ 開発で null ポインター例外を防ぐ方法 Aug 22, 2023 pm 12:40 PM

C++ 開発で null ポインター例外を防ぐ方法 概要: この記事では、ポインターの合理的な使用、ダングリング ポインターの回避、スマート ポインターの使用など、C++ 開発での null ポインター例外を防ぐ方法を主に紹介します。キーワード: C++ 開発、null ポインター例外、ポインター、ダングリング ポインター、スマート ポインター はじめに: C++ 開発では、null ポインター例外はよくある厄介な問題です。 Null ポインター例外は、コード内でポインターを正しく処理しなかったり、ダングリング ポインターを使用したりした場合に発生します。この記事では、null ポインター例外を防ぐいくつかの方法を紹介します。

Java でのパス トラバーサル攻撃の防止 Java でのパス トラバーサル攻撃の防止 Aug 09, 2023 pm 06:36 PM

Java でのパス トラバーサル攻撃の防止 インターネットの急速な発展に伴い、ネットワーク セキュリティの問題はますます重要になってきています。パス トラバーサル攻撃は、攻撃者がファイル パスを操作してシステム情報を取得したり、機密ファイルを読み取ったり、悪意のあるコードを実行したりする一般的なセキュリティ脆弱性です。 Java 開発では、パス トラバーサル攻撃を防ぐために適切な方法を講じる必要があります。パス トラバーサル攻撃の原理は、ユーザーが入力したファイル パスの誤った処理によって引き起こされます。パス トラバーサル攻撃がどのように機能するかを示す簡単なコード例を次に示します。

クロージャを使用してメモリリークを防ぐテクニックは何ですか? クロージャを使用してメモリリークを防ぐテクニックは何ですか? Jan 13, 2024 pm 01:01 PM

メモリリークを防ぐためにクロージャを使用するにはどうすればよいですか?メモリ リークとは、プログラムの実行中に、何らかの理由により、使用されなくなったメモリを再利用して時間内に解放できなくなり、最終的に過剰なメモリ使用量が発生し、プログラムのパフォーマンスと安定性に影響を与えることを意味します。 JavaScript では、クロージャはメモリ リークを引き起こす一般的な問題です。この記事では、クロージャとは何か、クロージャがどのようにメモリ リークを引き起こす可能性があるかを紹介し、クロージャを使用する際の考慮事項とサンプル コードを示します。閉鎖とは何ですか?クロージャとは、外部関数にアクセスできる関数内の関数を指します。

フロントエンドのパフォーマンス最適化モデルを明らかにする: Web サイトの速度を向上させる鍵 フロントエンドのパフォーマンス最適化モデルを明らかにする: Web サイトの速度を向上させる鍵 Feb 03, 2024 am 08:51 AM

フロントエンドのパフォーマンス最適化パターンが明らかに: Web サイトの速度を向上させる秘訣 要約: この記事では、コード構造の最適化、HTTP リクエストの削減、CDN の使用、リソースの圧縮、キャッシュと遅延の使用など、Web サイトの速度を向上させるフロントエンドのパフォーマンス最適化パターンをいくつか明らかにします。積み込みなどこれらのテクノロジーは、Web サイトのユーザー エクスペリエンスを向上させ、読み込み速度を向上させるのに役立ちます。 1. コード構造の最適化 フロントエンドのパフォーマンスを最適化する場合、コード構造の最適化は非常に重要なステップです。コード構造が複雑すぎるとブラウザの処理が遅くなるため、コードを読みやすくシンプルにする必要があります。