1

私は3つのテーブルを持っておりcountry_data, user_datatopic_data与えられたテーブル構造を持っています。

国データ:

name           | code
---------------|---------------
India          | IN
United States  | US
Australia      | AU

ユーザーデータ:

user_ip        | topic_code    | country
---------------|---------------|---------------
192.168.1.1    | topic_code_1  | India
192.168.1.2    | topic_code_2  | United States
192.168.1.3    | topic_code_3  | Australia

トピックデータ:

name           | code
---------------|---------------
topic_1        | topic_code_1
topic_2        | topic_code_2
topic_3        | topic_code_3

テーブルには約10万行ありuser_dataます。

私が望むのは、特定のトピックに対応する国コードを使用して、各国のユーザー数をフィルタリングする必要があるということです。たとえば、topic_2各国で閲覧したユーザーの数が必要です。要求される出力形式は次のとおりです。

country_code   | count
---------------|---------------
IN             | 150
US             | 120
AU             | 100

今私のクエリをチェックしてください:

SELECT cd.code, COUNT(ud.country) as count 
FROM topic_data as td, user_data as ud, country_data as cd 
WHERE td.name = 'topic_1' AND td.code = ud.topic_code AND ud.country = cd.name 
GROUP BY ud.country

これは phpmyadmin で実行を完了するのに約 2 秒かかります。php の Web ページでは、サーバーでもページの読み込みに 15 秒かかります。クエリで group by を削除します。つまりGROUP BY ud.country、実行に 30 秒以上かかり、最後の国コードとすべての国への訪問の合計が出力されます。私は何を間違っていますか?助けてください。

- - アップデート - -

外部キーを使用してテーブルを変更し、クエリも変更しました。今では電光石火の速さで動作します。助けてくれた人に感謝します。

4

2 に答える 2

2

クエリはそれほど悪くはありません。ただし、データの正規化は少し奇妙に見えます。たとえば、コードを検索するために名前に参加するだけで、テーブルにcountry(name) フィールドがあるのはなぜですか? 代わりに、私にとってより論理的なことは、国コード (または他のインデックス付きキー制約) ごとに国を参照することです。サンプルクエリに従ってコードが必要な場合は、これにより国への結合も節約できます。が大量のテーブルである場合は、その中のデータを最小限に抑えて、読み取り (密度) 時の IO を削減する必要があります。user_datacountryuser_data

また、余談JOINですが、句の代わりに使用して参加するWHEREと、コードの読みやすさが向上します.IMO:

SELECT cd.code, COUNT(ud.country) as count
FROM topic_data as td
  INNER JOIN user_data as ud
    ON td.code = ud.topic_code
  INNER JOIN country_data as cd
    ON ud.country = cd.name
WHERE td.name = 'topic_1'
GROUP BY ud.country;

パフォーマンスの問題に対処するには、次のインデックスが配置されていることを確認してください。

  • 索引付けtopic_data.name
  • user_data.topic_code外部キーおよびuser_data.country(またはuser_data.country_code、外部キーを に変更する場合user_data.country_code)のインデックスを作成します。
于 2013-09-05T06:55:27.180 に答える
0

代わりにこれを試してください:

INNER JOIN ステートメントで数値一致を使用するために以下のデータベース構造を使用すると、検索時間が短縮される可能性があるため、テーブルの id 列 (主キーなど) にインデックスを付けます。

**country_data**  
id|name           | code
--|---------------|---------------
1 |India          | IN
2 |United States  | US
3 |Australia      | AU

**user_data**
user_ip        | topic_id  | county_id
---------------|-----------|---------------
192.168.1.1    | 1         | 1
192.168.1.2    | 2         | 2
192.168.1.3    | 3         | 3

**topic_data**
id|name           
--|------------
1 |topic_1   
2 |topic_2
3 |topic_3 

次のような複数の INNER JOIN ステートメントを実行します。

SELECT cd.code, count(ud.topic_code) as count
FROM ud
INNER JOIN cd ON cd.id = ud.country
INNER JOIN td ON td.id = ud.topic_code
WHERE td.code='topic_1'
GROUP BY ud.country;
于 2013-09-05T09:46:59.517 に答える