1

次のクエリがあります。

SELECT DISTINCT c.id
FROM clients AS c
LEFT JOIN client_project AS cp ON (cp.client_id = c.id)
WHERE cp.project_id = 1
    AND c.active_flag = 1
ORDER BY c.client_name

order by を削除すると、クエリに 0.005 秒かかります。order by を使用すると、クエリに 1.8 ~ 1.9 秒かかります。に索引がありますclient_name

他に何が速度を改善しますか?

編集: c.id は主キーですが、client_project に複数のレコードが存在する可能性があるため、各 ID に対して複数のレコードが生成される場合があります。また、distinct を削除すると、クエリで 0.1 秒の差が生じます。

追加:これが私のクライアントテーブルです:

CREATE TABLE IF NOT EXISTS `clients` (
  `id` int(11) NOT NULL auto_increment,
...
  `organization` varchar(255) character set utf8 collate utf8_bin NOT NULL,
  `client_name` varchar(255) character set utf8 collate utf8_bin NOT NULL,
  `active_flag` tinyint(1) NOT NULL,
...
  PRIMARY KEY  (`id`),
  KEY `active_flag` (`active_flag`),
...
  KEY `organization` (`organization`),
  KEY `client_name` (`client_name`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

MySQL 5.0 の使用

4

9 に答える 9

2

あなたの編集を見て

その場合は EXISTS を使用してみてください

SELECT  c.id
FROM clients AS c
WHERE EXISTS (SELECT * FROM  client_project AS cp  
              WHERE cp.client_id = c.id and cp.project_id = 1)
AND c.active_flag = 1
于 2009-01-21T21:21:16.740 に答える
2

このキーを に追加してみてくださいclient_projects:

KEY(client_name, id, active_flag)
于 2009-01-22T01:13:29.047 に答える
1

おそらく、clients.id と client.active_flag にはインデックスがあるため、並べ替えを行う場合を除き、オプティマイザーが完全なテーブル (または追加のインデックス) にアクセスする必要はありません。

オプティマイザの計画を確認してください。mySQL では Explain だと思います。

client_name、id のインデックスが役立つ場合があります (そうでない場合もあります - 計画を確認してください)。

役立つかもしれないいくつかの追加の質問/アイデア/発言...

  • 選択から取得するのがIDだけの場合、なぜ名前で注文するのですか
  • 「cp.project_id」のwhere句がある場合、なぜ左結合を行うので、プロジェクトのないクライアントはとにかく返されません
  • 他のポスター (paul、eppz) に関しては、複数のプロジェクトを持つクライアントには「個別」が必要になる場合があります。したがって、別のアイデアは次のようなことをすることです

    select id from clients c where exists (select * from client_project cp where c.id = cp.client_id)

于 2009-01-21T21:22:52.603 に答える
1

解決策はありませんが、説明があります。

MySQL はテーブルごとに 1 つのインデックスのみを使用します。2 つのテーブルがあり、それらで使用されるインデックスは 1 つの主キー (WHERE cp.project_id = 1) であり、結合により、効率的に結合するために 2 番目のテーブル インデックスの使用が強制されます。

したがって、その後に ORDER BY を使用すると、MySQL がインデックスを使用して注文することができなくなります。インデックスを追加しても役に立ちません。EXPLAIN は、MySQL が各テーブルに使用するために選択したインデックスを表示します。インデックスを強制すると、クエリの他の部分が遅くなります。

于 2009-02-18T22:33:01.347 に答える
0

DB ベンダーに依存しない最適化もあれば、DB ベンダー固有の最適化もあります。ここでいくつかのことを試してみてください。

  • 他の場所で提案されているように、DISTINCT を削除します。
  • 内部結合の使用を検討してください。あなたの状況ではそれが実行可能な選択肢ではないかもしれないことを私は理解しています.

また、実行計画を実行して、クエリのどの部分が最も多くの時間を費やしているのか、その理由について、何が起こっているのかをよりよく把握します。詳細については、EXPLAINキーワードを参照してください。

于 2009-01-21T21:16:23.443 に答える
0

c.id は主キーですか? その場合、DISTINCT を実行するべきではありません。これは、既に区別されているためです。DISTINCT を強制すると、id で並べ替えられ、次に client_name で並べ替えられる可能性があります。

于 2009-01-21T21:11:14.077 に答える
0

でインデックスの使用を強制する必要がありますclient_name:

SELECT id
FROM (
  SELECT c.id,
    (
    SELECT 1
    FROM client_projects cp
    WHERE cp.client_id = c.id
      AND cp.project_id = 1
    LIMIT 1
    ) e
FROM clients c
FORCE INDEX (client_name)
WHERE c.active_flag = 1
ORDER BY
  client_name
) co
WHERE e IS NOT NULL
于 2009-02-18T15:15:50.463 に答える
-1

c.id は ID 列ですか? そうであれば、各 c.id が一意になるため、そこに DISTINCT は必要ないと思います。

編集

cp.project_id = 1 の場合でも、c.id は cp に複数のエントリを持つ可能性がありますか?

編集

クライアント名を選択していないのに、なぜクライアント名で注文したいのか、ちょっと不思議です。

于 2009-01-21T21:10:42.017 に答える
-2

返品すらしないのに、なぜクライアント名で注文するのですか?

また、明確なものが必要ですか?

とにかくwhere句が内部結合になる場合、なぜ左結合を行うのですか

この WHERE cp.project_id = 1 の代わりに AND cp.project_id = 1 を WHERE 句の前に持つことで、とにかく INNEr JOIN になります

于 2009-01-21T21:14:23.400 に答える