3

私は、他のテーブルの中でも、約 1,500 列のテーブルを持つ MySQL データベースを再設計中です。最初のテーブルに存在した各列/行のレコードを持つ 2 番目のテーブルを作成して、このテーブルのデータを正規化します。これらのテーブルを Master および MasterData と呼びましょう。Master には、そのテーブルのすべてのレコードが必要とする基本情報が含まれます。MasterData には、Master テーブルのレコードに関連するいくつかの追加データの値が含まれます。それでは、マスターが次のようになるとしましょう。

MasterID     Property1     Property2
1            Yes           No
2            No            Yes
3            Yes           Yes
4            No            No

MasterData が次のようになるとします。

MasterID     Property     Value
1            Property3    Yes
1            Property4    No
3            Property3    No
4            Property7    Yes

ここまで私と?このデータをクエリして、一致するマスター行ごとに 1 つの行だけを返し、関連するすべてのマスターデータ情報を含むにはどうすればよいですか。いくつかの例を検索して見つけましたが、データの実行に時間がかかりすぎます。前述の 1 つの巨大なテーブルの既存のデータに基づいて、テスト用の MasterData テーブルを作成しました。この結果、MasterData には約 450 万のレコードがあり、次のクエリは実行に時間がかかりすぎてタイムアウトになります。

SELECT Property1, Property2, Master.MasterID,
    GROUP_CONCAT(case when Property = "Property3" then Value end) as Property3, 
    GROUP_CONCAT(case when Property = "Property7" then Value end) as Property7
FROM Master LEFT JOIN MasterData USING (MasterID) GROUP BY MasterID
HAVING Property3='Yes' OR Property7='Yes';

また

Select * FROM Master AS M, MasterData AS MD1, MasterData AS MD2 
WHERE M.MasterID=MD1.MasterID AND MD1.Property='Property3' AND MD1.Value='Yes' 
AND M.MasterID=MD2.MasterID AND MD2.VAR='Property7' AND MD2.Value='Yes';

ここでも、MasterData のすべてのデータを、Master の列であるかのように 1 つの行で取得できるようにすることが目標です。これは可能ですか?

どんな助けでも大歓迎です!

4

1 に答える 1

2

ここでも、MasterData のすべてのデータを、Master の列であるかのように 1 つの行で取得できるようにすることが目標です。これは可能ですか?

あなたの目標を完全に理解することなく、厳密に言えば、おそらく可能だと言います。しかし、実用的な意味でそれが可能になる可能性はほとんどありません。最良のケース (1 つまたは 2 つのプロパティのみ) でさえ、パフォーマンスはおそらく最悪です。場合によっては (30 から 500 のプロパティの間で)、サーバーを完全にダウンさせる可能性があります。

正規化とは、「最初のテーブルに存在した各列/行のレコードを持つ 2 番目のテーブルを作成する」という意味ではありません。そんな遠く離れていても意味がありません。しかし、正規化によって実際に問題が解決される可能性があります。(私の経験では、ほとんどのデータベースの問題は構造的なものです。)

あなたがここで提案したのは、あなたが述べていない問題に対してうまく機能しない解決策です。StackOverflow の専門知識を最大限に活用するには、解決しようとしている問題と、試した解決策を記載してください。

データベースの正規化に関するウィキペディアの記事


このようなテーブルから始める場合。. .

create table master_data (
  master_id integer not null,
  property_name varchar(30) not null,
  property_value boolean not null default true,
  primary key (master_id, property_name)
);

insert into master_data values
(1, 'Property3', true),
(1, 'Property4', false),
(3, 'Property3', false),
(4, 'Property7', true);

. . . 次に、単純なクエリですべてのもののすべてのプロパティを取得できます。(すべてのプロパティがブール値であると仮定します。)

select * 
from master_data
order by master_id, property_name
--
1   Property3   t
1   Property4   f
3   Property3   f
4   Property7   t

アプリケーションコードはそれを非常に簡単にループできます。また、property_value が false であるすべての行を削除できる場合があります。

この構造により、それぞれのモノに対して無制限の数のプロパティが許可されます。ただし、a) 任意の数のプロパティを 1 行で返す、b) アプリケーション コードに最小限の変更を加えるという要件は、変更する必要があります。それを回避する方法はありません。


テーブルにこれらの行が含まれている場合。. .

insert into master_data values
(1, 'Property3', true),
(1, 'Property4', false),
(3, 'Property3', false),
(4, 'Property7', true),
(1, 'Property7', true);

資格のある「もの」のセットを取得し、そのセットをマスター データのテーブルに結合する 1 つの方法を次に示します。

select md.* 
from master_data md
inner join (select master_id
            from master_data
            where (
              (property_name = 'Property3' and property_value = true) or
              (property_name = 'Property7' and property_value = true)
            )
            group by master_id 
            having count(*) = 2 ) cd
  on (md.master_id = cd.master_id)

価値があるとしても、正規化はおそらく長期的なメンテナンスとパフォーマンスのための最善の策です。この種の構造 (上記) は正規化されていません。一般に、大量のデータ セットではパフォーマンスが低下します。(オプションの hstore モジュールを備えた PostgreSQL は、この点で MySQL よりも優れている可能性があります。)

于 2012-04-09T21:12:51.277 に答える