非正規化の欠点を理解しようとしています。次のデータベースがあるとします(School_has_Student
は非正規化されたテーブルです)。
非正規化を使用するときに直面する可能性のある問題は、INSERT
、UPDATE
、およびDELETE
の操作に関連していることを読みました。
これで、UPDATE
の問題が発生する理由がわかりました。これは、1つのデータを更新した場合、残りの関連データを更新する必要があるためです(たとえば、学生名「Paul」を更新した場合)。 「Student
テーブルで、School_has_Student
テーブルに2回存在する学生名「Paul」も更新する必要があります)が、なぜINSERT
とDELETE
も問題です。
注:ストレージスペースの増加もデメリットがあることは知っていますが、容量が非常に大きい現在のストレージデバイスでは大きなデメリットではないと思います。
モデルを非正規化する方法は例よりも多くありますが、あなたの場合、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
無効な情報が含まれています
また、ストレージは主要な懸念事項ではなく、モデルから誤った情報を導き出す可能性があることにも同意します。物事を少し伸ばすと、モデルとデータが私たちの公理になります。私たちのクエリの結果は、公理から推論できる定理です。公理が正しくないと、何でも推測できます。
削除には、更新と同じ問題、つまり作業の繰り返しがあります。
一度何かをすることは有限の時間を要します。
同じことを100回行うには、少なくとも 100倍の時間がかかります。
データベースに変更を加えるたびに、データファイルではなくトランザクションログに書き込むだけの場合でも、ディスクへの書き込みが発生することに注意してください。はい、ディスク容量は安価ですが、queryingデータベースのバッファキャッシュにメモリ内にあるデータブロックと比較して、..を...ディスクに書き込む....は...です。 。 スロー ......
あなたは本当にしなければならない以上のことをしたくありません。
また、where重複データが-誰か[else]が別のテーブルを追加した場合moreデータの重複コピー、すべての挿入、更新、削除を知っておく必要があります論理は言われたそれについてでなければなりません-彼らはそれを自分で解決する方法がありません。
非正規化にはさまざまな種類があります。次のようにメインテーブル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
の操作がさらに必要ですが、代わりにいくつかの利点があります。