2

私はこれらのテーブルを持っています:

create table person (
    person_id int unsigned auto_increment, 
    person_key varchar(40) not null, 
    primary key (person_id), 
    constraint uc_person_key unique (person_key)
) 
-- person_key is a varchar(40) that identifies an individual, unique 
-- person in the initial data that is imported from a CSV file to this table

create table marathon (
    marathon_id int unsigned auto_increment,  
    marathon_name varchar(60) not null, 
    primary key (marathon_id) 
)

create table person_marathon (
    person_marathon _id int unsigned auto_increment,  

    person_id int unsigned, 
    marathon_id int unsigned,

    primary key (person_marathon_id),
    foreign key person_id references person (person_id), 
    foreign key marathon_id references person (marathon_id),

    constraint uc_marathon_person unique (person_id, marathon_id)  
)

Person テーブルは、約 130,000 行を含む CSV によって設定されます。この CSV には、各個人の一意の varchar(40) とその他の個人データが含まれています。CSV に ID はありません。

マラソンごとに、1,000 ~ 30,000 人のリストを含む CSV を取得します。CSV には、基本的にperson_key、特定のマラソンに参加した人々を示す値のリストだけが含まれています。

person_marathonFK 関係を維持するためにデータをテーブルにインポートする最良の方法は何ですか?

これらは私が現在考えることができるアイデアです:

  • テーブルに挿入する前に、MySQL から情報を引き出し、PHP でデータをマージしてそこに取得しperson_id + person_keyます。person_marathonperson_idperson_marathon

  • 挿入には一時テーブルを使用してください...しかし、これは仕事のためであり、この特定のデータベースでは決して一時テーブルを使用しないように求められました

  • a はまったく使用せず、フィールドのみを使用しますが、a に参加する必要がperson_idあり、通常は良いことではありません。person_keyvarchar(40)

  • または、挿入の場合は、次のようにします(挿入する必要がありました。<hr>そうしないと、挿入全体がコードとしてフォーマットされません)。

    insert  into person_marathon 
    
    select  p.person_id, m.marathon_id
    
    from    ( select 'person_a' as p_name, 'marathon_a' as m_name union 
              select 'person_b' as p_name, 'marathon_a' as m_name ) 
              as imported_marathon_person_list 
    
            join person p 
               on p.person_name = imported_marathon_person_list.p_name
    
            join marathon m 
               on m.marathon_name = imported_marathon_person_list.m_name
    

    その挿入の問題は、PHP でビルドすると、簡単に 30,000アイテムimported_marathon_person_listになる可能性があるため、巨大になることです。select unionしかし、他にどのようにすればよいかわかりません。

4

1 に答える 1

2

小規模ではありますが、同様のデータ変換の問題を扱ってきました。私があなたの問題を正しく理解している場合 (私にはよくわかりません)、あなたの状況を難しくしている詳細は次のように思えます: 同じステップで 2 つのことをしようとしています:

  • CSV から mysql に多数の行をインポートし、
  • (扱いにくく望ましくない) varchar personkey 列ではなく、person_id と marathon_id を介して person-marathon 関連付けが機能するように変換を行います。

一言で言えば、これらの両方を同じステップで実行しないように、可能な限りのことを行います。これらの 2 つのステップに分割します。最初にすべてのデータを許容可能な形式でインポートし、後で最適化します。Mysql は、この種の変換を行うのに適した環境です。データを person テーブルと marathons テーブルにインポートすると、ID が自動的に設定されるからです。

ステップ 1: データのインポート

  • mysql 環境では、外部よりもデータ変換を実行する方が簡単だと思います。そのため、データを mysql に取得し、最適でなくても個人とマラソンの関連付けを保持する形式で行い、後で関連付けのアプローチを変更することを心配してください。
  • 一時テーブルについて言及していますが、必要ないと思います。person_marathons テーブルに一時列「personkey」を設定します。すべての関連付けをインポートするときは、ここでは person_id を空白のままにして、personkey だけをインポートします。重要なことは、personkey が、associations テーブルと persons テーブルの両方でインデックス付きの列であることを確認することです。その後、mysql が非効率的であることを心配することなく、後で調べて各 personkey に正しい person_id を入力できます。
  • マラソン テーブル データの性質についてはよくわかりません。参加する何千ものマラソンがありますか? もしそうなら、マラソンごとに 1 つのスプレッドシートを処理する仕事をうらやましく思いません。しかし、それが少ない場合は、マラソン テーブルを手動で設定できます。mysql にマラソン ID を生成させます。次に、各マラソンの person_marathon CSV をインポートするときに、そのマラソンに関連する各関連付けでそのマラソン ID を指定してください。

データのインポートが完了すると、次の 3 つのテーブルが作成されます。 * persons - 醜い personkey と、新しく生成された person_id とその他のフィールド * marathons - この時点で marathon_id が必要ですよね? 新しく生成された番号か、古いシステムから引き継いだ番号のいずれかです。* person_marathons - このテーブルには marathon_id が入力されており、marathons テーブルの正しい行を指しているはずですよね? personkey (醜いが存在する) と person_id (まだ null) もあります。

ステップ 2: personkey を使用して、関連付けテーブルの各行に person_id を入力します。

次に、直接 Mysql を使用するか、単純な PHP スクリプトを記述して、persons_marathons テーブルの各行に person_id を入力します。mysql にこれを直接実行させるのに問題がある場合は、一度に 1 つの行を処理する php スクリプトを作成することがよくあります。この手順は簡単です。

  1. person_id が null であるが personkey が null でない任意の 1 行を検索します
  2. その personkey の person_id を調べる
  3. その行の関連付けテーブルにその person_id を書き込みます

PHP にこれを 100 回繰り返してからスクリプトを終了するように指示するか、タイムアウトの問題やその他の問題が発生し続ける場合は 1000 回行うことができます。

この変換には膨大な数のルックアップが含まれますが、各ルックアップは 1 つの行に対してのみ必要です。mysql (または PHP) に「データセット全体を頭に保持する」ように要求する必要がないため、これは魅力的です。

この時点で、関連付けテーブルのすべての行に person_id が入力されているはずです。personkey 列を安全に削除できるようになりました。ほら、効率的な外部キーができました。

于 2013-07-22T17:41:18.123 に答える