SQL パフォーマンスの最適化は、プログラマーにとって大きな課題です。なぜなら、私たちはよくこの問題に遭遇するからです。プロジェクトを開発するとき、自分たちでテストする機能体験はとても良いと感じますが、実際のプロジェクトが立ち上げられると、パフォーマンスが大幅に向上します。データの面では、システムの顧客エクスペリエンスはますます悪化しています。もちろん、フレームワークや無理なコードに加えて、SQL が最適化されていないことが主な原因であり、そのためにシステムがどんどん遅くなっていきます。
私は小さな会社で働いているので、根本原因を治療するよりも症状を治療する方が良い場合もあると考えています。注意すべき問題がいくつかあります。
1. データベース テーブルの設計、特に主キーの設計は合理的である必要があります。テーブル内のデータ量が非常に大きい場合、主キーの設計は、ROWID と同様に意味があってはなりません。 SQL ServerのGUID、HibernateのUUIDなど。もちろん、ディクショナリ表の中には柔軟に処理できるものもありますし、物理主キーであることを意識する必要はありません。主キーの設計では、通常、複合主キーは使用されません。
2. 合理的なインデックス作成。インデックスは強力なツールであり、データ クエリを高速化する優れた手段です。ただし、すべてのフィールドを追加しないでください。インデックスの原理は本の目次と同じです。本の目次がほぼすべて同じ名前である場合、目次に従って特定の内容をどれだけ早く見つけることができるかが想像できます。 ?インデックスは必ずしも一意である必要はありませんが、同一のレコードが多すぎてはなりません。さらに、インデックスを追加すると、テーブルをエクスポートして別のデータベースにインポートするときに、TEMP テーブル スペースが増加し、このとき、UNDOTBS01 テーブル スペースも低下することがわかります。異常に大きいです。したがって、インデックスは両刃の剣であり、合理的に適用する必要があります。
3. SQL の最適化に関する非常に専門的な記事をインターネットでいくつか見たことがありますが、自分のプロジェクトではそれらを使用できていないと感じています。代わりに、私はプロジェクト中に実験を続け、いくつかの基本原則を発見しました。個人的には、SQL 最適化の原則は 1 つだけだと考えています。それは、クエリの範囲をできるだけ狭めることです。これにより効率は確実に向上します。Oracle 自体が作成する SQL を最適化できるので、私たちがしなければならないことは次のとおりです。クエリの範囲をできるだけ狭くする このことについて言えば、インデックス作成はクエリの速度を向上させるための強力なツールであると誰もが間違いなく考えると思います。 。
最適化が必要な SQL のほとんどは複数テーブルの結合クエリであり、複数テーブルの結合には水平結合と垂直結合も含まれます。最もよく使用されるのは垂直結合です。水平接続とは、一般に、2 つのテーブルのフィールド構造が基本的に同じであり、一方のテーブルの一部のデータ レコードを別のテーブルの一部のレコードに変更する必要があること (つまり、行+行) を意味します。垂直接続とは、テーブル A からクエリ対象のフィールドをいくつか取り出し、テーブル B からクエリ対象のフィールドをいくつか取り出し、テーブル A とテーブル B から取り出したテーブルを共通部分、つまり列 + 列を使用して垂直に接続することを意味します。
水平結合ステートメント: select a.column1,a.column2 from tableA a Union all select b.column1,b.column2 from tableB b
横方向に接続する場合は、列数が同じであり、対応するフィールド列のデータ型が同じである必要があることに注意してください。実際、結合されるテーブルは、まったく同じ、もう一方のコピーであると考えることができます。マージしたい列に異なる列がある場合、または列がまったくない場合は、次の方法を使用できます。
select d.dname,d.loc from dept1 d Union all select '' dname, e.loc from dept e, "'' dname" を見ると、代わりに空の文字列を使用できることが簡単にわかります。はフィールドではないため、マージできます。
垂直結合ステートメント: select a.column1,a.column2 from tableA a 完全外部結合 select b.column3,b.column4 from tableB b on a.aid=b.bid ここで...、これは完全外部結合形式です。この速度は確かに非常に高速ですが、まったく表示したくない結果行がいくつかあるため、このクエリは気に入らないかもしれません。通常の状況では、左外部結合と右外部結合がよく使用されます。この 2 つの違いは、左外部結合は主に、on 以降の左側の結合フィールドに対応するテーブルに基づいているのに対し、右外部結合はその逆であることです。もちろん、左結合、右結合も使用できます。使用中、やはり外部接続の方が比較的速いことが分かりました。
垂直接続クエリの効率を高めるには、クエリをネストする方法があります。以下はプロジェクトの実際の例です。
c.customerid、c.receivedmoney、c.tollcollector、c.receiveddate、c.yearmonth、c.receivedlatefee、を選択します。
c.receivedfee、c.receivedappend、c.jmman、c.jmmoney、c.name、d.chargeint from
(a.customerid、a.receivedmoney、a.tollcollector、a.receiveddate、a.yearmonth、a.receivedlatefee、を選択します
a.receivedfee、a.receivedappend、a.jmman、a.jmmoney、b.name from
(rf.customerid、rf.receivedmoney、rf.tollcollector、rf.receiveddate、rf.yearmonth、rf.receivedlatefee、を選択します
rf.receivedfee,rf.receivedappend,rf.jmman,rf.jmmoney from sf_receivedfee rf ここで
rf.electriccompanyid='1000000001' および rf.dealsign=0 および rf.yearmonth in(200811,200901,200903,200804,200805,200806,200807)
および rf.customerid=1000052545) 左外部結合 (xt_employee xe から xe.employeeid,xe.name を選択) b (a.tollcollector=b.employeeid)
c 左外部結合 (cp.customerid=1000052545 の sf_chargeprotocol cp から cp.chargeint,cp.customerid を選択) d
c.customerid=d.customerid で
この例では、最初にほぼ同じ条件を使用して各テーブルから必要なレコードをフィルタリングし、その後レコードを結合していることがわかります。実際に使用すると、直接リンク クエリよりも 60 倍近く高速であることがわかります。見苦しくて読みにくいですが、SQL のパフォーマンスの問題は解決されます。使用する原理は依然として、最初にスコープを絞り込み、次に接続クエリを実行することです。接続してからフィルタリングする場合、これは 2 つのテーブルを結合し、条件に基づいてデータをフェッチするのと同じです。