14

ブラジルの株式市場データを SQL Server データベースにインポートしています。現在、株式、オプション、フォワードの 3 種類の資産からの価格情報を含むテーブルがあります。私はまだ 2006 年のデータを使用しており、テーブルには 50 万件を超えるレコードがあります。12 年分のデータをインポートする必要があるため、テーブルは確実に 100 万レコードを超えます。

さて、最適化のための最初のアプローチは、データを最小サイズに保つことだったので、次の列で行サイズを平均 60 バイトに減らしました。

[在庫] [int] NOT NULL
[日付] [smalldatetime] NOT NULL
[オープン] [スモールマネー] NOT NULL
[高] [少額] NOT NULL
[低] [少額] NOT NULL
[Close] [smallmoney] NOT NULL
[取引] [int] NOT NULL
[数量] [bigint] NOT NULL
[ボリューム] [金額] NOT NULL

さて、最適化のための 2 番目のアプローチは、クラスター化インデックスを作成することでした。実際には、プライマリ インデックスは自動的にクラスター化され、Stock フィールドと Date フィールドを含む複合インデックスにしました。これはユニークです。同じ日に同じ株の 2 つの相場データを取得することはできません。

クラスタ化されたインデックスは、同じ株からの引用符がまとめられ、おそらく日付順に並べられるようにします。この 2 番目の情報は本当ですか?

現在、50 万件のレコードがあるため、特定のアセットから700 件の見積もりを選択するのに約 200ミリ秒かかります。この数は、テーブルが大きくなるにつれて高くなると思います。

3 番目のアプローチとして、テーブルを 3 つのテーブルに分割し、それぞれが特定の市場 (株式、オプション、フォワード) に対応することを考えています。これにより、おそらくテーブル サイズが 1/3 に削減されます。さて、このアプローチは役に立ちますか、それともあまり重要ではありませんか? 現在、テーブルのサイズは 50 MB であるため、問題なく RAM に完全に収まります。

もう 1 つの方法は、SQL Server のパーティション機能を使用することです。私はそれについてあまり知りませんが、通常、テーブルが大きく、I/O レイテンシを減らすために複数のディスクにまたがることができる場合に使用されると思いますよね? この場合、パーティショニングは役に立ちますか? 最新の値 (最近の年) と最も古い値を別のテーブルに分割できると思います. 最新のデータを探す確率は高くなります. 分割が小さいとおそらく速くなりますよね?

これを最速にするための他の良いアプローチは何でしょうか? テーブルの主な選択用途は、特定の資産から特定の範囲のレコードを検索することです。たとえば、資産 X の最新の 3 か月などです。別の用途もありますが、これが最も一般的であり、3k 以上で実行される可能性があります。ユーザーを同時に。

4

9 に答える 9

11
  1. 100万レコードの場合、これはテーブルの分割や非正規化などの異常な最適化手法を必要とする特に大きなテーブルとは見なされません。しかし、これらの決定は、影響を与えない通常の手段をすべて試したときに行われます。標準のクエリ手法を使用する機能。

ここで、最適化の2番目のアプローチは、クラスター化インデックスを作成することでした。実際、プライマリインデックスは自動的に分類され、StockフィールドとDateフィールドを含む複合インデックスにしました。これはユニークで、同じ日に同じ株の2つの見積もりデータを持つことはできません。

クラスター化されたインデックスは、同じ株からの相場が一緒にとどまり、おそらく日付順に並べられていることを確認します。この2番目の情報は本当ですか?

それは論理的に真実です-クラスター化されたインデックスは、ディスク上のレコードの論理的な順序を定義します。これは、あなたが心配する必要があるすべてです。SQL Serverは、物理ブロック内での並べ替えのオーバーヘッドを回避できますが、それでも動作するかのように動作するため、重要ではありません。いずれにせよ、1つの株のクエリはおそらく1ページまたは2ページの読み取りになります。オプティマイザーは、読み取られたページ内の順序付けされていないデータからあまり恩恵を受けません。

現在、50万件のレコードがあるため、特定の資産から700件の見積もりを選択するのに約200ミリ秒かかります。テーブルが大きくなるにつれて、この数は増えると思います。

必ずしも重要ではありません。テーブルサイズとクエリ速度の間に線形関係はありません。通常、より重要な考慮事項がたくさんあります。あなたが説明する範囲では、私はそれについて心配しません。それがあなたが心配している理由ですか?200ミリ秒は、テーブルが読み込まれるポイントに到達し、現実的なテストを開始して、実際のパフォーマンスについてより良いアイデアを得るのに十分なほど素晴らしいと思います。

ここで、3番目のアプローチとして、テーブルを3つのテーブルに分割し、それぞれが特定の市場(株式、オプション、先渡)に対応することを考えています。これにより、テーブルサイズが1/3に削減される可能性があります。さて、このアプローチは役に立ちますか、それともそれほど重要ではありませんか?現在、テーブルのサイズは50 MBなので、問題なくRAMに完全に収まります。

いいえ!この種の最適化は時期尚早であり、おそらく死産です。

もう1つのアプローチは、SQLServerのパーティション機能を使用することです。

同じコメント。厳密に論理的で完全に正規化されたスキーマ設計に長い間固執することができます。

これを可能な限り最速にするための他の良いアプローチは何でしょうか?

最良の最初のステップは、在庫のクラスタリングです。1秒あたりに挿入される複数のレコードを確認するまで、挿入速度はまったく重要ではありません。ここでは、そのアクティビティの近くには何も表示されません。これにより、株式に関連付けられたすべてのレコードが効率的に読み取られるため、最大効率に近づくはずです。これが最も一般的なインデックスのようです。テストに基づいて、さらに最適化を行う必要があります。

于 2008-12-13T23:54:54.503 に答える
10

百万のレコードは実際にはそれほど大きくありません。検索に時間がかかりすぎるように聞こえますが、検索対象の列はインデックスに登録されていますか?

相変わらず、最初の呼び出しポートはSQLプロファイラーとクエリプランエバリュエーターである必要があります。SQL Serverに、関心のあるクエリをどのように処理するかを尋ねます。追加のインデックスなどの変更を提案するようにSQLServerに依頼することもできると思います。

私はまだパーティショニングなどに取り掛かっていません-あなたが言うように、それは現時点ではすべて快適にメモリにあるはずなので、あなたの問題はインデックスの欠落である可能性が高いと思います。

于 2008-12-03T16:32:18.410 に答える
3

インデックスを再評価します...これが最も重要な部分です。データのサイズは実際には重要ではありませんが、速度を上げるためだけではありません。

そのテーブルのインデックスを再構築し、最も必要な列の複合インデックスを作成することをお勧めします。さまざまなインデックスで再生されるレコードがわずかしかないため、テーブルにすべての履歴データが含まれると、新しいことを試すのは非常に面倒になります。

クエリを確認したら、クエリプランエバリュエーターを友達にして、エンジンが適切なインデックスを使用しているかどうかを確認します。

私はあなたの最後の投稿を読んだばかりですが、私が得られないことが1つあります。データを挿入している間、テーブルを検索していますか?同時に?。何のために?挿入するということは、1つのレコードまたは10万のレコードを意味しますか?どのように挿入しますか?一つずつ?

しかし、ここでも重要なのはインデックスです。パーティション分割などをいじらないでください。特にミリオンレコードの場合は、1億5000万レコードのテーブルがあり、40kの特定のレコードを返すとエンジンに約1500ミリ秒かかります。 。

于 2008-12-03T16:52:08.933 に答える
3

最初に、そのクエリの実行プランを確認してください。インデックスが使用されていることを確認してください。私はそれを見つけました。百万のレコードは多くありません。いくつかの見通しを与えるために、3000万行のインベントリテーブルがあり、大量のテーブルを結合して多くの計算を行ったクエリ全体を200MS未満で実行できました。Quad proc 64ビットサーバーでは、大幅に多くのレコードを保持できるため、パーティション分割を気にする必要がないことがわかりました。

SQL Profierを使用して実行プランを確認するか、SQLManagementStudioまたはQueryAnalyzerからクエリを実行することができます。

于 2008-12-03T16:35:18.920 に答える
1

私は学区で働いており、各生徒の出席を追跡する必要があります。それが私たちがお金を稼ぐ方法です。各学生の毎日の出席マークを保持している私のテーブルは、現在3890万レコードの大きさです。これから、一人の生徒の出席をすぐに引き出すことができます。このテーブルには4つのインデックス(主キーを含む)があります。クラスター化されたインデックスは学生/日付であり、すべての学生のレコードをその順序で保持します。学生の古いレコードが挿入された場合のそれに関して、このテーブルへの挿入にヒットしましたが、それは私たちの目的にとって価値のあるリスクです。

選択速度に関しては、私は確かにあなたの状況でキャッシングを利用します。

于 2008-12-03T16:35:04.723 に答える
1

あなたの主キーは(株式、日付)の複合であり、クラスター化されていると述べました。これは、テーブルが Stock で編成され、次に Date で編成されることを意味します。新しい行を挿入するたびに、テーブルの中央に挿入する必要があり、これにより、他の行が他のページに押し出される (ページ分割) 可能性があります。

主キーを (Date, Stock) に反転し、Stock に非クラスター化インデックスを追加して、特定の Stock をすばやく検索できるようにすることをお勧めします。これにより、挿入は常にテーブルの最後に行われ (日付順に挿入すると仮定)、テーブルの残りの部分には影響せず、ページ分割の可能性が低くなります。

于 2008-12-03T22:41:42.253 に答える
0

実行プランは、クラスター化インデックスを非常にうまく使用していることを示していますが、非常に重要な事実を忘れてしまいました。まだデータを挿入しています。インサートがテーブルを頻繁にロックしている可能性があります。このボトルネックを確認する方法はありますか?

実行プランには、ロックの問題について何も示されていないようです。

現在、このデータは履歴のみであり、インポートプロセスが終了すると、挿入が停止し、頻度が大幅に低下します。しかし、すぐにリアルタイムデータ用のより大きなテーブルが作成されます。これは、この一定の挿入の問題に悩まされ、このテーブルよりも大きくなります。したがって、この種の状況を最適化するためのアプローチは大歓迎です。

于 2008-12-03T16:47:01.547 に答える
0

実際には、プライマリ インデックスは自動的にクラスター化され、Stock フィールドと Date フィールドを含む複合インデックスにしました。これはユニークです。同じ日に同じ株の 2 つの相場データを取得することはできません。

クラスタ化されたインデックスにより、同じ株からの相場がまとめられ、おそらく日付順に並べられます。この 2 番目の情報は本当ですか?

SQL Server のインデックスは、常にインデックス内の列の順序で並べ替えられます。したがって、[stock,date] のインデックスは、最初に在庫でソートされ、次に在庫内で日付でソートされます。[date, stock] のインデックスは、最初に日付でソートされ、次に日付内で在庫でソートされます。

クエリを実行するときは、常にインデックスの最初の列を WHERE 部分に含める必要があります。そうしないと、インデックスを効率的に使用できません。

特定の問題について: 株式の日付範囲クエリが最も一般的な使用法である場合、[date, stock] で主キーを実行すると、データが日付順にディスクに保存され、最速のアクセスが得られるはずです。必要に応じて他のインデックスを構築します。大量の新しいデータを挿入した後、インデックスの再構築/統計の更新を行います。

于 2008-12-13T22:58:18.673 に答える
0

別の解決策は、毎年の履歴テーブルを作成し、このすべてのテーブルを履歴データベースに配置し、それらすべてに入力してから、適切なインデックスを作成することです。これが完了したら、二度とそれらに触れる必要はありません。なぜデータを挿入し続ける必要があるのでしょうか? これらすべてのテーブルをクエリするには、それらを「すべて結合」するだけです:p

現在の年のテーブルは、この履歴テーブルとは大きく異なるはずです。あなたが外出先でレコードを挿入することを計画していると私が理解したのは、一括挿入または類似の何かを時々実行するなど、別のことを計画することです。もちろん、これはすべて、あなたが何をしたいかによって異なります。

ここでの問題は設計にあるようです。私なら新しいデザインにします。あなたが今持っているものは、私が理解しているものには適していません。

于 2008-12-03T17:03:55.210 に答える