2016-07-05 5 views
0

私のクエリは、データがヌルでない各フィールドのボリュームを返します。別名でスピードアップカウント

SELECT COUNT(field1) AS field1, COUNT(field2) AS field2, COUNT(field3) AS field3 
FROM (
    SELECT field1, field2, field3 
    FROM table1, table2 
    WHERE table1.id=table2.idt1 
    ORDER BY table1.id ASC 
    LIMIT 10000 
) AS rq 

table1.id is table1とtable2.idt1の主キーは、table2の2次キーです。 このクエリはよく完璧に働いているが、私はこの

SELECT COUNT(DISTINCT(field1)) AS field1, COUNT(DISTINCT(field2)) AS field2, COUNT(DISTINCT(field3)) AS field3 
FROM (
    SELECT field1, field2, field3 
    FROM table1, table2 
    WHERE table1.id=table2.idt1 
    ORDER BY table1.id ASC 
    LIMIT 10000 
) AS rq 

の問題のように、各フィールドのDISTINCTボリュームを返却する必要がある場合は...クエリが取り組んでいるし始めると仕事をするが、性能はですもちろん、DISTINCT句がない場合よりもはるかに遅くなります。

私はこのDISTINCTのカウントをスピードアップすることができますどのようにbtree

CREATE INDEX field1_index ON table1 USING btree (field1) 
CREATE INDEX field2_index ON table1 USING btree (field2) 
CREATE INDEX field3_index ON table2 USING btree (field3) 

でTABLE1とtable2のあるインデックスの各フィールド?たぶん、より良いインデックスがありますか?ヘルプ

+2

適切で明示的な 'JOIN'構文を使うことを学ぶべきです。 –

+0

'DISTINCT'は***ではありません*** ***関数 –

+0

ジョインを作成し、その非常に結合されたばかりの行から別個の値を数えるのは何ですか?参加しないと数えない方が良いでしょうか? – Tomalak

答えて

0

ため

おかげPostgresは非常によくCOUNT(DISTINCT)を最適化しません。あなたはそのような表現を複数持っているので、少し難しくなります。私は、ウィンドウ関数と条件付きの集約を使用することをお勧めするつもりです:

SELECT SUM(CASE WHEN seqnum_1 = 1 THEN 1 ELSE 0 END) as field1, 
     SUM(CASE WHEN seqnum_2 = 1 THEN 1 ELSE 0 END) as field2, 
     SUM(CASE WHEN seqnum_3 = 1 THEN 1 ELSE 0 END) as field3 
FROM (SELECT field1, field2, field3, 
      ROW_NUMBER() OVER (PARTITION BY field1 ORDER BY field1) as seqnum_1, 
      ROW_NUMBER() OVER (PARTITION BY field2 ORDER BY field2) as seqnum_2, 
      ROW_NUMBER() OVER (PARTITION BY field3 ORDER BY field3) as seqnum_3 
     FROM table1 JOIN 
      table2 
      ON table1.id=table2.idt1 
     ORDER BY table1.id ASC 
     LIMIT 10000 
    ) rq 

EDIT:

row_number()limitに処理されるかもしれないことを私に起こります。このバージョンを試してみてください:

SELECT SUM(CASE WHEN seqnum_1 = 1 THEN 1 ELSE 0 END) as field1, 
     SUM(CASE WHEN seqnum_2 = 1 THEN 1 ELSE 0 END) as field2, 
     SUM(CASE WHEN seqnum_3 = 1 THEN 1 ELSE 0 END) as field3 
FROM (SELECT field1, field2, field3, 
      ROW_NUMBER() OVER (PARTITION BY field1 ORDER BY field1) as seqnum_1, 
      ROW_NUMBER() OVER (PARTITION BY field2 ORDER BY field2) as seqnum_2, 
      ROW_NUMBER() OVER (PARTITION BY field3 ORDER BY field3) as seqnum_3 
     FROM (SELECT field1, field2, field3 
      FROM table1 JOIN 
       table2 
       ON table1.id = table2.idt1 
      ORDER BY table1.id ASC 
      LIMIT 10000 
      ) t 
    ) rq 
+0

@Gordonありがとうございますが、私の場合は遅すぎる、さらに悪いようです。それは数分から実行され、それはまだ仕上げていません。 DISTINCT句を使用して5分間。 – Macbernie

+0

実際、あなたの編集方法はうまくいきますが、実行には818秒、基本DISTINCT句 – Macbernie

+0

@Macbernieは437秒です。 。 。これらのフィールドのタイプは何ですか? 10,000行のいくつかの 'count(distinct)'はそれほど長くはならないでしょう。 –

0

私は大きなテーブルで同様のことを試しました。 (12百万行)

DISTINCTがないと10秒かかります。

コードのようにDISTINCTでは19秒かかります。

Putingは、サブクエリ内のDISTINCTは他の事11秒

SELECT COUNT(field1) AS field1, COUNT(field2) AS field2, COUNT(field3) AS field3 
FROM (
    SELECT DISTINCT(field1) AS field1, DISTINCT(field2) AS field2, DISTINCT(field3) AS field3 
    FROM table1, table2 
    WHERE table1.id=table2.idt1 
    ORDER BY table1.id ASC 
    LIMIT 10000 
) AS rq 

を取るだけNULLデータをフィルタしたい場合は、あなたの代わりに明確な使用のWHERE句でこれを行うことができます。