スパースデータ:RDBMSでの効率的なストレージと取得
-
03-07-2019 - |
質問
次のように、プロジェクトリビジョン全体のソースファイルメトリックの値を表すテーブルがあります。
Revision FileA FileB FileC FileD FileE ...
1 45 3 12 123 124
2 45 3 12 123 124
3 45 3 12 123 124
4 48 3 12 123 124
5 48 3 12 123 124
6 48 3 12 123 124
7 48 15 12 123 124
(上記のデータのリレーショナルビューは異なります。各行には、Revision、FileId、Valueの列が含まれます。データの計算元のファイルとそのリビジョンはSubversionリポジトリに格納されているため、リレーショナルスキーマでリポジトリの構造を表します。)
10000リビジョンで最大23750個のファイルが存在する可能性があります(これは ImageMagick 描画プログラム)。ご覧のとおり、ほとんどの値は連続するリビジョン間で同じであるため、テーブルの有用なデータは非常にまばらです。データを保存する方法を探しています
- レプリケーションを回避し、スペースを効率的に使用します(現在、非スパース表現には、保存するデータの10%未満に260 GB(データ+インデックス)が必要です)
- SQLクエリを使用して(リビジョンまたはファイルを明示的にループすることなく)特定のリビジョンの値を効率的に取得できます
- 特定のメトリック値のリビジョンを効率的に取得できます。
理想的には、ソリューションは特定の RDBMS に依存してはならず、< href = "http://en.wikipedia.org/wiki/Hibernate_%28Java%29" rel = "nofollow noreferrer"> Hibernate 。これが不可能な場合、Hibernate、MySQL、またはPostgreSQL固有の機能を使用して生活できます。
解決
これは私がそれをモデル化する方法です。 RevisionsテーブルとFilesテーブルは、説明の必要がないため省略しました。
CREATE TABLE Revision_Files
(
start_revision_number INT NOT NULL,
end_revision_number INT NOT NULL,
file_number INT NOT NULL,
value INT NOT NULL,
CONSTRAINT PK_Revision_Files PRIMARY KEY CLUSTERED (start_revision_number, file_number),
CONSTRAINT CHK_Revision_Files_start_before_end CHECK (start_revision_number <= end_revision_number)
)
GO
特定のリビジョンのファイルのすべての値を取得するには、次のクエリを使用できます。外部結合を使用してファイルテーブルに結合すると、そのリビジョンの値が定義されていないファイルを取得できます。
SELECT
REV.revision_number,
RF.file_number,
RF.value
FROM
Revisions REV
INNER JOIN Revision_Files RF ON
RF.start_revision_number <= REV.revision_number AND
RF.end_revision_number >= REV.revision_number
GO
3番目のポイントであなたが望むものを正しく理解していると仮定すると、これにより、特定のファイルが特定の値を持つすべてのリビジョンを取得できます。
SELECT
REV.revision_number
FROM
Revision_Files RF
INNER JOIN Revisions REV ON
REV.revision_number BETWEEN RF.start_revision_number AND RF.end_revision_number
WHERE
RF.file_number = @file_number AND
RF.value = @value
GO