1

私は最近、巨大な「エンタープライズ」アプリケーションを扱う会社で働き始めました。前の仕事でデータベースを設計しましたが、ここにはデータベース アーキテクチャ部門全体があり、私はその一部ではありません。

データベースの奇妙な点の 1 つは、ユーザーが表示したい日付範囲を提供する代わりに、開始日と終了日を含む (グローバル一時) テーブル "TMP_PARM_RANG" に結合する一連のビューがあることです。メインアプリがリクエストの処理を開始するたびに、最初に行うことは「DELETE FROM TMP_PARM_RANG;」それからそれに挿入します。

これは奇妙なやり方のように思えますし、あまり安全ではありませんが、ここにいる他の誰もがそれで問題ないようです。これは正常ですか、それとも私の不安は有効ですか?

更新 トランザクションとクライアントごとのロックを使用しているため、ほとんどの同時実行の問題から保護されていることに言及する必要があります。また、すべてが に依存する数百ではないにしても、文字通り数十のビューがありますTMP_PARM_RANG

4

9 に答える 9

3

データベースが oracle の場合は、グローバル一時テーブルである可能性があります。すべてのセッションが独自のバージョンのテーブルを参照し、挿入/削除が他のユーザーに影響を与えることはありません。

于 2009-01-07T16:28:18.527 に答える
3

これを正しく理解していますか?

次のようなビューがあります。

SELECT * FROM some_table, tmp_parm_rang
  WHERE some_table.date_column BETWEEN tmp_parm_rang.start_date AND tmp_parm_rang.end_date;

次に、フロントエンドでユーザーが日付範囲を入力すると、アプリケーションは次のことを行います。

  1. TMP_PARM_RANG からすべての既存の行を削除します
  2. ユーザーの値を含む新しい行を TMP_PARM_RANG に挿入します
  3. ビューからすべての行を選択します

TMP_PARM_RANG への変更がコミットまたはロールバックされるのだろうか? もしそうならいつ? 一時テーブルですか、それとも通常のテーブルですか? 基本的に、これらの質問に対する回答によっては、プロセスを複数のユーザーが並行して実行するのは安全ではない場合があります。これが事実である場合、彼らはすでにそれを発見して対処していただろうと期待していますが、誰が知っていますか?

たとえそれがスレッドセーフな方法で行われたとしても、単純なクエリ操作のためにデータベースに変更を加えることはあまり意味がありません。これらの DELETE および INSERT は、完全に不要な REDO/UNDO (または非 Oracle データベースで同等のもの) を生成しています。

同じ目標を達成するための単純でより一般的な方法は、このクエリを実行して、ユーザーの入力をクエリ パラメータにバインドすることです。

SELECT * FROM some_table WHERE some_table.date_column BETWEEN ? AND ?;
于 2009-01-07T16:32:26.597 に答える
2

このテーブルには何らかのビジネス上の理由があるはずです。実際にはパーティション化されたビューであり、パーティション化フィールドとして日付を使用していた日付がハードコーディングされたビューを見てきました。また、夏時間に対処するときのようにテーブルに参加することも見てきました。DST 中に発生したすべてのアクティビティを返すビューを想像してください。そして、これらのどれも削除してテーブルに挿入することはありません...それはただ奇妙です

したがって、これには掘り下げる必要があるより深い理由があるか、それとも当時は良い考えのように思えたが、なぜそのように行われたのかは、部族の知識として失われています.

于 2009-01-07T16:27:30.040 に答える
1

個人的には、かなり奇妙な出来事だと思います。そして、あなたが言っていることから、プロセスを同時に呼び出す2つのメソッドは非常に興味深いものになる可能性があります.

通常、日付範囲はビューのフィルターとして実行され、他のテーブルに格納された外部の値によって駆動されることはありません。

これを正当化できる唯一の理由は、一度に 1 回しか実行されず、複数のストアド プロシージャにまたがる複数の操作に日付が必要な複数ステップのプロセスがあった場合です。

于 2009-01-07T16:23:31.577 に答える
1

複数の範囲をサポートできるようになると思います。たとえば、2008 年 1 月 1 日から 2009 年 1 月 1 日、および 2006 年 1 月 1 日から 2007 年 1 月 1 日までのすべての日付を返し、2006 年のデータと 2008 年のデータを比較できます。バインドされたパラメーターの単一のペアでは、これを行うことはできませんでした。また、Oracle がビューのクエリ プランのキャッシュをどのように行っているかはわかりませんが、おそらくそれと関係があるのでしょうか? ビューの一部として日付列がチェックされると、サーバーは、日付が常にチェックされると想定するプランをキャッシュできます。

ここでいくつかの推測を投げるだけです:)

また、あなたは書いた:

トランザクションとクライアントごとのロックを使用しているため、ほとんどの同時実行の問題から保護されていることに言及する必要があります。

これにより、同時実行によるデータの一貫性の問題を防ぐことができますが、同時実行によるパフォーマンスの問題に関しては問題になります。

于 2009-01-07T16:58:11.960 に答える
0

主キーの次の一意の値を生成するために、アプリケーションにも追加しますか?

これらの人々は共有状態の概念を理解していないか、共有状態の理由を理解していないようです。

于 2009-01-07T16:26:49.277 に答える
0

それは私にはかなり奇妙なアルゴリズムのように思えます。同時実行をどのように処理するのだろうか-トランザクションにラップされていますか?

誰かが WHERE 句の書き方がわからなかったように思えます。

于 2009-01-07T16:27:25.953 に答える
0

ビューはおそらく一時テーブルとして使用されます。SQL Server では、この目的のためにテーブル変数または一時テーブル (# / ##) を使用できます。ビューの作成は専門家によって推奨されていませんが、私が取り組んでいるテーブルが互いに参照していないため (真剣に FK はありません!)、SSRS プロジェクト用に多くのビューを作成しました。データベース設計の欠陥を回避する必要があります。それが私がビューをたくさん使っている理由です。

于 2009-01-07T16:56:14.053 に答える
0

あなたがコメントしたグローバル一時テーブル GTT アプローチがここで使用されているため、この方法はマルチユーザー システムに関しては確かに安全であるため、問題はありません。これが Oracle の場合、GTT が適切に結合されるようにシステムが適切なレベルの動的サンプリングを使用しているか、GTT に関する統計を提供するために DBMS_STATS への呼び出しが行われているかを確認したいと思います。

于 2009-01-07T18:12:43.730 に答える