質問をすることでしか得られない、回答やアドバイスがある。

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

新規登録して質問してみよう
ただいま回答率
85.31%
DB2

DB2(IBM Database2)は、IBMのリレーショナルデータベース管理システム製品です。 UNIXとWindows、IBM社のメインフレームOS用が用意されており、 幅広いプラットフォームに対応しています。

Q&A

解決済

5回答

412閲覧

全項目をselectする場合「select *」と「select カラム1 カラム2 ・・・」のパフォーマンスは違うのか?

enoeno

総合スコア22

DB2

DB2(IBM Database2)は、IBMのリレーショナルデータベース管理システム製品です。 UNIXとWindows、IBM社のメインフレームOS用が用意されており、 幅広いプラットフォームに対応しています。

0グッド

0クリップ

投稿2025/04/30 05:56

DB2での質問になります。(DB2に固有な話とは思えませんが)
質問内容はタイトルのとおりなのですが、全項目を取得しなければならないselectの場合、*で引っ張ってくるとパフォーマンスに影響するので全項目をコーディングしなければならないと言われたことがあります。

これって都市伝説でしょうか?

前提:

  • カラム数は120程度
  • 全レコード数は1000万レコード程度のテーブル
  • レコード長800~1000バイト程度
  • 一回のselectで20レコード程度取得(さすがにwhereは指定しています)

背景:

  • PL/SQLにてカーソル定義でselectをコードしている
  • カーソルforループでレコードを取り出して汎用ルーチンにパラメーターで渡している
  • 汎用ルーチンのインターフェースとしてパラメーター定義に%ROWTYPEが付加されている
  • 上記にてレコードにカラムを追加したらコンパイルでエラーとなり、調べたらカーソルのselectのコーディングにもカラムを追加しなければならないとわかったが、どうしてそこは「select *」しておかないのかと聞いたらタイトルのような理由と言われた
  • パフォーマンスはハードが稼ぐものであり、将来の保守によるバグを生まないコードとして「select *」が望ましいのではないかと自分は思ってしまった・・・

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

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

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

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

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

guest

回答5

0

将来に渡ってすべての列を取得する処理ということで、将来列が追加されたらその列も含めて取得する必要があり、まさに今やっている案件がその話に当たります。

であれば、「select *」とすべき だと思います。 全取得が目的ですので、列挙とのパフォーマンスの差はありません。

また、なにしろすべてのカラムの情報が必要であるという意図も「select *」で表現できるので、よりよいと言えるでしょう
ただし、「select * は使うべきでない」という考えの方もいると思うので、コメントに意図的であることを明記しておくのがいいでしょう。

投稿2025/04/30 09:59

TakaiY

総合スコア14311

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

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

0

ベストアンサー

こんにちは。

知っている限りの話では、select * でパフォーマンスが落ちると言われているのは往々にして「意図せず不要な列の取得が行われる場合がある」からであって、現在存在する全ての列を取得するクエリと比較する場合はパフォーマンスに違いはないはずです。
select * を使うか全列列挙するかの判断基準はパフォーマンスではなく、テーブルのカラムに変更が加わった際に自然と追従してよいのか、あるいは変更を検出 (エラーになる) できてほしいのかで選ぶものです。

一般には、プログラムというものは特定のカラムの存在を想定して記述するものなので、仮に全列参照する場合でも select * は使わない方が良い、というプラクティスのことを言っているのかもしれません。
例えば、仮に今参照しているテーブルから特定の列が削除されたとき、ふんわり動いてほしいのか、即座にエラーで止まってほしいのかを改めて考えてみてください。

逆に言えば、どのように列が変化してもそのまま全てを参照したい、というような特殊な要件下など、select * を使う方が適切であるケースもあります。

投稿2025/04/30 09:34

tamoto

総合スコア4304

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

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

enoeno

2025/04/30 10:06 編集

>現在存在する全ての列を取得するクエリと比較する場合はパフォーマンスに違いはないはずです。 ありがとうございます。とても腹落ちしました。こういった都市伝説は困りものですね。。。 将来どこまで行ってもすべての列取得がアプリとしての要件なので、パフォーマンス云々が嘘と分かりとても安心しました。 ベストアンサーにさせていただきます!!
guest

0

DB2での質問になります。

全項目を取得しなければならないselectの場合、*で引っ張ってくるとパフォーマンスに影響するので全項目をコーディングしなければならない

(身も蓋もないですが)「場合による」としか言いようがありません。

Db2 for Linux, UNIX and Windows: 効率的な SELECT ステートメント

効率的な SELECT ステートメントを作成するための、以下の指針を考慮してください。

  • 必要な列だけを指定します。 1 つのアスタリスク (*) を使ってすべての列を指定すると、不必要な処理が実行されます

Db2 for z/OS: SELECT * の使用による影響

一般に、SELECT * は、非表示列以外のすべての列を選択する場合にのみ使用する必要があります。

通常、Db2 が選択した列の数に依存しているため、必要な列のみを選択する必要があります。 SELECT * を使用するのは、隠し列を除くすべての列を選択する必要があることが確実であるときだけにしてください。 (隠し列は、SELECT * を指定しても戻されません。) すべての列の選択に代わる方法の 1 つは、必要とする列だけが定義されているビューを使用し、そのビューのアクセスに SELECT * を使用することです。 選択したすべての列がソート操作(SELECT DISTINCTとSELECT…)に参加している場合は、SELECT * を避けてください。例えば、 UNIONなどです。 )

Db2 for Linux, UNIX and Windows: 隠し列

表列が暗黙的な隠し属性によって定義されると、明示的に参照されなければ、その列は使用できません。 例えば、SELECT * 照会を表に対して実行した場合、暗黙的な隠し列は結果表に返されません。 暗黙的な隠し列は、列名を指定できる場所ならどこででも、明示的な方法で参照が可能です。

Db2 for z/OS: SELECT ステートメントによるデータの取り出し

SELECT * は、動的 SQL およびビュー定義で使用する場合に最も適しています。 静的SQLでSELECT * を使用できますが、ホスト変数の互換性とパフォーマンスへの影響の可能性があるため、お勧めしません。 SELECT * が参照表に列を追加するとします。 その列の受信ホスト変数を定義しない場合、エラーが発生するか、追加列のデータが取得されない可能性があります。

アスタリスクの代わりに、静的SELECT ステートメントに列名をリストすると、SELECT * の発生可能問題を回避できます。 また、受け取りホスト変数と結果表中の列の対応関係を知ることもできます。

投稿2025/04/30 07:47

編集2025/04/30 08:20
sk.exe

総合スコア1077

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

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

enoeno

2025/04/30 09:06

色々と参考情報をありかとうございました。 前提としては「隠し列を除くすべての列を選択する必要があることが確実であるとき」に該当するということです。 将来に渡ってすべての列を取得する処理ということで、将来列が追加されたらその列も含めて取得する必要があり、まさに今やっている案件がその話に当たります。 >(身も蓋もないですが)「場合による」としか言いようがありません。 それは重々承知なのですが、書いたようなテーブル規模と応答数であっても「select *」を避けなければならないほどの大きな時間差が出るものなのか知見をお持ちではないでしょうか?
sk.exe

2025/04/30 10:26

> 書いたようなテーブル規模と応答数であっても「select *」を > 避けなければならないほどの大きな時間差が出るものなのか そちらの環境に関しては、実際に両者のケースを測定し、比較しない限り判りません。 またそのデータベースに同時アクセスするユーザーの数や、アクセスされる頻度も不明です。 判らない以上、勝手な憶測でもっともらしい見解を第三者が述べるわけにはいきません。 程度問題は差し置いて「パフォーマンスに影響する『可能性がある』」のは確かで、 けして嘘や都市伝説などではない、ということしか言えません。 > レコードにカラムを追加したらコンパイルでエラーとなり、 > 調べたらカーソルのselectのコーディングにもカラムを > 追加しなければならないとわかった 上記を文面通りのままに受け取るならば、そもそもの原因は 「select * を使用していない(明示的に列名を記述している)ことを 事前に把握せずにコードを書いたから」であるように思えます。 少なくとも「select * を使用していないこと」は直接の原因ではないでしょう。 > 将来の保守によるバグを生まないコードとして「select *」が望ましいのではないか 保守性の高いコードを書くことはもちろん大事ですが、だからといってパフォーマンスを 無視していいわけでもありません。 「パフォーマンスの低い SQL / コードが実行されることによってレスポンスが(極端に)遅くなる」 という現象もバグの一種と言えますし。 詰まるところ、「場合によってうまく使い分ける」より他にないかと。
guest

0

レスポンスに関しては推論より、実際に投入される環境の実行計画で確認すべきです。
その上で疑問になる点がある時に質問した方がより効果的です。

特にDB2を利用されている方は他のDBMSより少ないですし。

私は記述を極力少なくする派なので、*が使えるなら*を使用しますが、ネストが深いSQLなどでは、項目を明示するしかないDBMSもあります。

投稿2025/04/30 10:08

sazi

総合スコア25430

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

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

0

将来の保守によるバグを生まないコードとして「select *」が望ましいのではないか

一般に「select *」はパフォーマンスやセキュリティを犠牲にしてデバッグなどテスト用に使うものなので、原則カラム名を列記して使うのが賢明です。

投稿2025/04/30 07:12

yambejp

総合スコア117691

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

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

enoeno

2025/04/30 09:01

セキュリティーはひとまず要件にはないとして、問題はパフォーマンスなのですがどの程度落ちるのでしょうか? 前提に書いた通りのテーブル規模と応答件数だとしてでかまいません。 微々たるものであれば、全件読み必須のアプリ処理においてカラム追加を忘れてしまうようなメンテナンス性の悪いコードを排除できればと考えています。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.31%

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

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

質問する

関連した質問