🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

Q&A

解決済

2回答

12952閲覧

PostgreSQLのDistinctが遅いので改善したい

kuuritar

総合スコア38

PostgreSQL

PostgreSQLはオープンソースのオブジェクトリレーショナルデータベース管理システムです。 Oracle Databaseで使われるPL/SQLを参考に実装されたビルトイン言語で、Windows、 Mac、Linux、UNIX、MSなどいくつものプラットフォームに対応しています。

SQL

SQL(Structured Query Language)は、リレーショナルデータベース管理システム (RDBMS)のデータベース言語です。大きく分けて、データ定義言語(DDL)、データ操作言語(DML)、データ制御言語(DCL)の3つで構成されており、プログラム上でSQL文を生成して、RDBMSに命令を出し、RDBに必要なデータを格納できます。また、格納したデータを引き出すことも可能です。

0グッド

0クリップ

投稿2019/11/25 08:37

編集2019/11/25 09:38

PostgreSQLで以下のようなusersテーブルがあるとします。

idnameemail
1テスト太郎1test1@test.com
2テスト太郎2test2@test.com
3テスト太郎3test1@test.com
4テスト太郎4test1@test.com
5テスト太郎5test2@test.com
6テスト太郎6test1@test.com

emailは重複するので、ユニークなemail数を調べたいです。
シンプルにすれば
SELECT COUNT(DISTINCT email) FROM users;
で良いですが、これだと非常に速度が遅いです。

これをどうにかして高速化できないでしょうか?

試したこと

group byを利用して見ましたが、特に速度は改善されませんでした。
SELECT email FROM users group by email;

調べたこと

EXISTS句というのを使えば高速化できるという記事をいくつか拝見しましたが、他テーブルとの関連はなく、あくまでusersテーブル内で完結するものなので使えなさそうでした。

解決したいこと

どうにかDISTINCT以外を利用して高速化させたいのですが、何か良い案はありますか?
ここまでシンプルなものだとこれ以上早くはできないでしょうか?

追記

すみません、少し質問内容がふわっとしていたので追記させてください。

今回はIndex等は考慮せず(全てのカラムにIndexはないものとして)、上記テーブルでユニークなemail数を調べたいという要件を満たす最速のクエリが知りたいというのが質問になります。
レコード数が多い場合、SELECT COUNT(email) FROM usersよりSELECT COUNT(distinct email) FROM usersの方が遅いのは明らかで、SELECT COUNT(distinct email) FROM usersより早いユニークなemail数を調べたいという要件を満たすクエリが知りたいです。
単純にないというのであれば別のアプローチ(Indexの見直し等)を行おうと思っています。

それでもexplainの結果等があった方が良いというのであれば追記します。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

退会済みユーザー

退会済みユーザー

2019/11/25 09:05 編集

通常の実行SQLの直前に「EXPLAIN 」句を加えて実行計画を取得してみた結果を、質問文に追記してください。それと、emailは文字列データだと察しますが、データ型はvarchar(n)、char(n)、textのうちどれでしょうか。
Orlofsky

2019/11/25 09:06

以下の内容を質問に追記されては? email 列でインデックスを作成してなかったらインデックスを追加してみては? users テーブルのレコード件数は何件ほどでしょうか? 2つのSELECT文の実行計画を追記しては?https://qiita.com/bunty/items/c6e7bfa99c1814811863
m.ts10806

2019/11/25 22:47 編集

「それでも」もなにもSQLの速度改善で真っ先に確認するのは実行計画でしょう。小手先だけでやるものではありません。INDEX追加も実行結果を元に行うのが通常です。 常套手段を取らないのであれば差しのべられる手はありませんよ。 情報不足の作業依頼でしかありません。自分で解決してください。
guest

回答2

0

ベストアンサー

今回はIndex等は考慮せず(全てのカラムにIndexはないものとして)

適切なインデックスを設定することはパフォーマンスの改善に効果的な場合が多いです。もちろん、わたしは貴殿の上司ではありませんから、インデックスの追加を強制はしません。

投稿2019/11/25 10:29

Orlofsky

総合スコア16417

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Orlofsky

2019/11/26 15:32

「質問への追記・修正」に書いたけど、インデックスを追加する前後で実行計画はどう変わりましたか? Markdown で[コード]で表示して欲しいので「質問」に追加してください。 で、インデックスを追加してどの程度パフォーマンスは改善されましたか?
guest

0

インデックスを張れ、以上。

11.2. インデックスの種類
emailを対象にした検索や絞り込みを行う上で、
インデックスの性能や機能を考慮した適切なインデックス設計を行うべき、
って話のようです。

本番でない開発中の状況だと勝手に想像しますが、
そういう状況こそ、インデックスなし、ありで
EXPLAINによる実行計画を比較検討する絶好の機会だと思うのですが。
インデックスがなければFULL SCANで時間かかりまくりだと察します。

投稿2019/11/25 10:16

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問