web-dev-qa-db-ja.com

更新は非正規化の唯一の欠点ですか?

非正規化の欠点を理解しようとしています。次のデータベースがあるとします(School_has_Studentは非正規化されたテーブルです)。

enter image description here

非正規化を使用するときに直面する可能性のある問題は、INSERTUPDATE、およびDELETEの操作に関連していることを読みました。

これで、UPDATEの問題が発生する理由がわかりました。これは、1つのデータを更新した場合、残りの関連データを更新する必要があるためです(たとえば、学生名「Paul」を更新した場合)。 「Studentテーブルで、School_has_Studentテーブルに2回存在する学生名「Paul」も更新する必要があります)が、なぜINSERTDELETEも問題です。

注:ストレージスペースの増加もデメリットがあることは知っていますが、容量が非常に大きい現在のストレージデバイスでは大きなデメリットではないと思います。

1
Tom

モデルを非正規化する方法は例よりも多くありますが、あなたの場合、INSERT異常の例は次のようになります。

INSERT INTO SCOOL_HAS_STUDENT 
    (school_id, school_name, student_id, student_name)
VALUES
    (2, 'A third school', 1, 'Tim');

つまり.

SELECT distinct school_name 
FROM SCOOL_HAS_STUDENT 
WHERE school_id = 2

無効な情報が含まれています

また、ストレージは主要な懸念事項ではなく、モデルから誤った情報を導き出す可能性があることにも同意します。物事を少し伸ばすと、モデルとデータが私たちの公理になります。私たちのクエリの結果は、公理から推論できる定理です。公理が正しくないと、何でも推測できます。

1
Lennart

削除には、更新と同じ問題、つまり作業の繰り返しがあります。

一度何かをすることは有限の時間を要します。

同じことを100回行うには、少なくとも 100倍の時間がかかります。

データベースに変更を加えるたびに、データファイルではなくトランザクションログに書き込むだけの場合でも、ディスクへの書き込みが発生することに注意してください。はい、ディスク容量は安価ですが、queryingデータベースのバッファキャッシュにメモリ内にあるデータブロックと比較して、..を...ディスクに書き込む....は...です。 。 スロー ......
あなたは本当にしなければならない以上のことをしたくありません。

また、where重複データが-誰か[else]が別のテーブルを追加した場合moreデータの重複コピー、すべての挿入、更新、削除を知っておく必要があります論理は言われたそれについてでなければなりません-彼らはそれを自分で解決する方法がありません。

0
Phill W.

非正規化にはさまざまな種類があります。次のようにメインテーブルreadoutsを作成できるとします。

CREATE TABLE `readouts` (
  `sensorID` INT(10) UNSIGNED NOT NULL,
  `timestamp` TIMESTAMP NOT NULL,
  `value` FLOAT(9,5) NOT NULL,
  PRIMARY KEY (`sensorID`, `timestamp`)
);
+----------+-----------+-------+
| sensorID | timestamp | value |
+----------+-----------+-------+

テーブルには、多くのセンサーからの読み取り値が格納されます。各センサーの最後の読み取りが必要な場合は、次のようなクエリを実行する必要があります。

SELECT a.*
  FROM readouts AS a
  JOIN ( SELECT sensorID
              , MAX(timestamp) AS timestamp
          GROUP BY sensorID
       ) AS b  ON b.timestamp = a.timestamp
              AND b.sensorID  = a.sensorID
 ORDER BY sensorID ASC
;

テーブルreadoutsが適切にインデックス付けされている場合でも、これは非常に重いクエリです。同じ構造のテーブルを作成することでデータベースを非正規化できますが、sensorIDのUNIQUE制約は次のとおりです。

CREATE TABLE `last_readouts` (
  `sensorID` INT(10) UNSIGNED NOT NULL,
  `timestamp` TIMESTAMP NOT NULL,
  `value` FLOAT(9,5) NOT NULL,
  PRIMARY KEY (`sensorID`)
);

次に、両方のテーブルへの着信読み出しをINSERTする必要があります。 2番目のテーブルは特別な方法で挿入する必要があります。

INSERT INTO last_readouts 
     VALUES (sID, ts, val) 
     ON DUPLICATE KEY UPDATE 
        `timestamp` = ts
         value = val
;

この追加のINSERTは、非正規化の挿入関連の欠点です。しかし、利点はクエリの最小コストです

SELECT * FROM last_readouts;

DELETEの欠点も同じです。DELETEの操作がさらに必要ですが、代わりにいくつかの利点があります。

0
Kondybas