人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

MySQLのJOINについて再度質問です。

前回の質問で、テンポラリテーブルを使用する方法を教えていただきました。
テンポラリテーブルは”一時テーブル”だと言うことですが、数万件のデータを扱う場合でも、問題になることはないのでしょうか?(現状では特に問題ありませんが、気になったもので。。)

それから、A,B,Cと三つのテーブルがあったとして、BとCに一致するテーブル(仮にBCとします)をAと結合させたい場合、テンポラリテーブルを使って先にBCの一時テーブルを作成し、その後にAとBCを結合するしかないのでしょうか?(ちなみにAとBCはLEFT JOINでの結合になります)

共にデータ処理のパフォーマンスを重視したいので、速度的に「こうした方が良い」という方法がありましたら、アドバイスいただければと思います。

MySQLのバージョンは4.0.x系でお願いします。

●質問者: kt26
●カテゴリ:ウェブ制作
✍キーワード:BC MySQL それから アドバイス テンポ
○ 状態 :終了
└ 回答数 : 4/4件

▽最新の回答へ

1 ● b-wind
●30ポイント

あまりに範囲が広すぎて答えづらいのですが、


テンポラリテーブルは”一時テーブル”だと言うことですが、数万件のデータを扱う場合でも、問題になることはないのでしょうか?

テンポラリだからといって見た目は普通のテーブルと変わらないので、同様に考えればよい。

つまり数万件単位のレコードがあるテンポラリテーブルが作成される状況は大量の書き込みが一度に発生するので、

ほぼ使い物にならないことが想定される。


A,B,Cと三つのテーブルがあったとして、BとCに一致するテーブル(仮にBCとします)をAと結合させたい場合

ちょっと意味がよくわからないのですが、

A LEFT JOIN B INNER JOIN C

の形は特に問題ないです。


速度的な問題は個々の状況によってさまざまに変わるので一概に言えることはないです。

◎質問者からの返答

Aを個人情報とします。2万件ほどあります。Aに対する住所はBに入っており、Cに郵便番号や都道府県コードなどが入っています。(郵政の郵便番号CSVの値です)


Bに入っている住所とCとを結合し、一致するデータを作成する。

その結果とAとを結合したいという意味です。


ですので、数万単位のレコードが存在するので、テンポラリテーブルの場合は「使い物にならない」という状況になると、どうしたらよいものかと思い、悩んでいます。

(現在はBの登録数が少ないので、表示に違和感はありませんが。)


また、JOINの方法ですが、

SELECT * FROM A LEFT JOIN B ON A.id=B.id INNER JOIN C ON B.c_id=C.c_id

とすると、Aの件数に問わず、INNER JOIN後の登録数しか表示されません。


BとCの結合結果に問わず、Aの値を出力したいです。


2 ● b-wind
●30ポイント

Bに入っている住所とCとを結合し、一致するデータを作成する。

その結果とAとを結合したいという意味です。

なにかの検索条件はあるのでは?

検索条件によっては工夫の使用がありますが、全件出力であればどうしようもないです。

この例ではテンポラリテーブルを作る必要はなさそうですが。


BとCの結合結果に問わず、Aの値を出力したいです。

SELECT * FROM B INNER JOIN C USING ( c_id ) RIGHT JOIN A ON A.id = B.id 

でいいんでは?

◎質問者からの返答

ありがとうございます。参考にさせていただきます。


3 ● chuken_kenkou
●30ポイント

テンポラリ・テーブル(一時表)を使う提案を受けたのは、MySQL 4.0では、サブクエリが使えないため、代替手段としてだと推察します。

表A,B,Cで、先にBとCをinner join、その結果とAをleft joinするなら、MySQL 4.0でも、テンポラリ・テーブルを使わずに実現できるように思います。

(MySQL 4.0の環境がなく、実記確認できていません)

複数のinner joinやleft joinを行なう場合、ジョインはその記述順で行なわれます。また、「( )」を使って、ジョインの順序を指定できます。

select * from A
 left join 
 (B inner join C on B.id=C.id)
 on A.id=B.id

4 ● chuken_kenkou
●40ポイント

BとCは、c_idで結合しているのを見逃していました。

-- 記述形式1
select * from A
 left join 
 (B inner join C on B.c_id=C.c_id)
 on A.id=B.id

-- 記述形式2
select * from A
 left join 
 (B inner join C using(c_id))
 on A.id=B.id

Aのid、Bのid、Cのc_idは、primary keyになっているのでしょうか?

primary keyを指定すると、内部的にインデクスが作成されますが、Bのc_idにも、インデクスを定義しているでしょうか?

データ件数が数千件以上になるなら、インデクスを定義した方が良いと思います。

定義するには、以下のような方法があります。

-- create tableで、uniqueを使って定義
create table B
(id int primary key,
 c_id int,
 jusho varchar(30), 
 unique(c_id))

-- create indexで定義
create unique index インデクス名 on B(c_id)
◎質問者からの返答

はい。primary keyになっています。

調べていくと、「検索が遅い」というのは、どうもインデクスを定義してなかった

事によるかもしれません。

上記はあくまでも例なので、ID以外も結合対象になるのですが、

インデクスを指定すると早くなりました。


また、joinの方法についてもさんこうになりました。ありがとうございます。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ