
初めまして、最近SQLをかじり始めたぺーぺーです。
効率の悪いSELECT文しか書けずに困っています。
下記のテーブルsoftware_tableから、
・name列「oracle」
・version値が最大
のレコードに含まれるid(=3)を拾ってきたいのですが、自分の頭では副問い合わせを使う方法か、ソートを使う方法しか思いつきません。
問題は副問い合わせ・ソートを使うと計算コストが大きくなってしまうことで、できることなら副問い合わせ・ソートを使わずに解決したいのですが、何か方法はないものでしょうか?
よろしくお願い致します。
-----------------------------
software_table
idnameversion
1oracle1
2oracle2
3oracle3
4postgres1
5postgres2
6postgres3
7postgres4
-----------------------------
■副問い合わせを使った方法
SELECT id FROM software_table
WHERE
name = 'oracle' AND
version = (SELECT max(version) FROM software_table WHERE name = 'oracle');
■ソートを使った例
SELECT id FROM software_table
WHERE name = 'oracle' ORDER BY version DESC LIMIT 1 OFFSET 0;
-----------------------------
No.2ベストアンサー
- 回答日時:
数十万件だと毎回実行するにはなかなか厳しい感じですね。
状況から察するに, name にインデックスを張ってもあまり有効に働かないみたいですね。
アプリケーションを考慮して, name と versionの最大値 の組み合わせの抽出が頻繁に行われるようでしたら,
name と versionの最大値の二つの列を持つ参照用のテーブルを作成して, そこから参照するようにしてはどうでしょうか。
software_table に INSERT/UPDATE/DELETE が発生したら, 上記のテーブルをトリガを利用して書き換えればよいと思います。
# もちろんプログラム側で対応しても構いません
name と versionの最大値の組み合わせの参照がそれほど発生せず, アプリケーション的にも多少時間がかかるのが許されるならば,
副問い合わせやソートのやり方でもよいと思いますよ。
なるほどと思いました。で、nameとversionの最大値の組み合わせでの参照は頻繁に行われるため、試しに参照用のテーブルを作成して実行計画を見てみました。
のですが、、速度を計測してみたところレスポンスは副問い合わせを使ったときの方が早いようです(レコード3万件で実験)。
おそらくテーブルの結合に時間がかかってしまってることが原因ではないかと考えています。
しかし今回はたまたまテーブル結合が無いケースでしたが、もともとのSELECT文でテーブル結合をする必要がある場合には、参照用のテーブルを作ったほうが早いかもしれませんね。
何度もアドバイスをくださってありがとうございます。もはや改善は無理っぽい感じですが、重要な部分なのでもう一日だけ頑張ってみようと思います^^;
No.1
- 回答日時:
基本的には副問い合わせやソートはコストのかかる処理です。
ただ, それはデータ件数が数十万, 数百万にもなった場合に実際に体感できる負荷として顕在化してきます。
software_table に格納されるデータ量の見積もりはどのくらいを想定しているのでしょうか?
格納されて高々数千件というレベルであれば, 書かれてある副問い合わせやソートを使っても全く問題ないと思います。
また, name属性で検索結果がかなり絞り込めるのであれば,
その後に MAX関数で最大値を求めようがソートで並び替えをしようがコストはほとんどかかりません。
副問い合わせやソートは必ずしも悪というわけではなく, 状況によって使い分ければよいと思います。
ちなみに GROUP BY を使って以下のようにもかけます。
が, 特に効率がいいということはありません ^^;
SELECT name, MAX(version) FROM software_table
WHERE name = 'oracle' GROUP BY name;
お返事ありがとうございます。
お返事をいただいて真っ先に思いましたのは、「SELECT文を書く場合、絞り込みの順番を意識することがすごく重要だ」ということです。絞込みやすい順にwhere句を記述していくとそれだけでパフォーマンスが上がるんですね。DBエンジニアとしては当たり前の知識なのでしょうが、勉強になりました。
ただ「nameの絞込み自体のコストが大きい」ことは確かで、それが今回のケースでは問題になりそうだと感じました。メインの文と副問い合わせ文の両方でnameで絞込みをかけなければいけなくなっているので。。
なお、格納されるデータ量ですが、詳しくはわかりませんが数十万件くらいにはなる予定です。
お返事ありがとうございました^-^
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Oracle sqlで質問です。 aテーブルとbテーブルがあり、下記のsqlで取得したidとnameに一致しないレ 1 2022/04/20 20:34
- MySQL 下記の問合せを行うクエリを、PhpMyAdminで作成して実行せよ。 「名前(first name) 1 2023/06/24 13:03
- MySQL 書籍の内容はまともでしょうか? 1 2023/01/22 03:07
- MySQL SQLです。下記の問合せを行うクエリを、PhpMyAdminで作成して実行せよ。 「昨年の各月の総降 1 2023/07/01 00:32
- Oracle Oracleですがsqlで質問です。 サブクエリ内で番号というカラムで昇順の1レコード目を取得したい 3 2023/05/22 10:02
- Oracle SQL update方法 2 2022/06/22 14:07
- PHP コメント機能に返信欄を矢印で追加したい 1 2022/05/09 21:17
- PostgreSQL SQLで検索結果の記事を表示したい 1 2022/04/28 21:03
- MySQL PhpMyAdminで作成して実行せよ。 東京23区を、皇居を中心とした4つのエリア(南東, 南西, 1 2023/06/11 11:58
- MySQL SQLです。こんな感じですか?あってますか? うまくいきません教えてくださいお願いします 1 2023/07/08 15:27
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
テーブルからのselectにおいて...
-
postgreSQLのint型は桁数指定が...
-
pg_queryで変数の取り扱い方
-
indexを使おうとしない間違った...
-
賢いSQL文がわからない
-
PostgressからMySQL(MariaDB)...
-
phpPgAdminからSQL文を発行し、...
-
データを削除しても表領域の使...
-
異なるスキーマからデータを抽...
-
ORA-00959: 表領域'****'は...
-
他ファイルのテーブルの情報を...
-
Viewにインデックスは張れ...
-
シーケンシャルアクセスについて
-
DELETE文でFROM句を省略した場合
-
カラムの存在チェック
-
DBリンク経由の参照について
-
Access レコードを追加できませ...
-
SQLでスキーマ名(所有者名)の...
-
INDEXの無効化
-
特定のスキーマのテーブルを一...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
テーブルからのselectにおいて...
-
postgreSQLのint型は桁数指定が...
-
クエリアナライザのsp_helpコマ...
-
UNIQUEをつけたときのINDEXテー...
-
PostgressからMySQL(MariaDB)...
-
PostgresSQL8.4でツリー上に取...
-
SQL SELECT文 別テーブルのレコ...
-
SQL文作成のお願い
-
Postgresqlの自己結合について
-
チェックボックスから、データ...
-
Oracle でのデータベースサイズ...
-
ビット演算結果の取得
-
Perl DBI でSELECT ilikeの結果...
-
検索スピードの速い方法を教え...
-
ベスト3の抽出方法
-
もうちょっと賢いSELECT文が書...
-
こんばんは。
-
テーブル作成 外部参照 配列
-
自動で生成されるユニークID
-
plpgsqlのエスケープ文字について
おすすめ情報