- PR -

SQLServerのSQL「SELECT * FROM 〜」でレスポンスは低下するのか

投稿者投稿内容
NAO
ぬし
会議室デビュー日: 2001/10/24
投稿数: 1256
お住まい・勤務地: 神奈川のはずれから東京の下町
投稿日時: 2006-05-26 12:15
引用:

『「SELECT * FROM テーブル名」の記述方法はレスポンスが悪くなるから使用すべきではない。
 列名を全て記述するべきだ』



*でやっても全列記述してもレスポンスだけを気にするならば
全く意味の無い事です。

実際さんもクエリープランで確かめているわけでしょう?

事実を突きつけてあげたほうが良いと思います

まともな考えを持っていれば聞き入れてくれるでしょう。

可読性を考えるならば列名記述の方が良いと思います。
保守性を考えるならば*で書いておいた方が後々列名を変更したり、
追加したりした場合にSQL文の変更が伴わなくて済むと思います。

_________________
Inspired Ambitious
ISMS Assistant Auditor
明智重蔵
大ベテラン
会議室デビュー日: 2005/09/05
投稿数: 127
投稿日時: 2006-05-26 12:33
select * from
で、不要な列まで選択してるとなれば

DataTableを作った時に余計な列まで作る
ネットワークを流れるデータが増える

などで
データが多ければレスポンスが低下するんじゃないですか?
maru
ぬし
会議室デビュー日: 2003/01/27
投稿数: 412
投稿日時: 2006-05-26 12:51
みなさんの言われるように、それぞれの特性を理解して状況に応じた使い分けをすれば
いいと思います。

* は「レスポンスが悪くなるから使用すべきではない」というのは間違いと思います。

先輩が言われているのは「SELECT 以下に全ての列名を列挙する」ではなく、
「SELECT 以下に必要な列名を列挙する」ではないですか?

私は列項目が多いテーブルで、項目数の半分以上をSelectして、1回のアクセスに数行
〜数十行程度取得して、体感速度的(※)に問題ないようなものに関しては、保守性のこ
とを考慮して * をよく使います。
※当然、クエリアナライザなどで通信量やI/Oなどの数値的な面も考慮します

ダラダラと列名を列挙するのはゾッとします。
大量データを取得するなどパフォーマンス重視の部分は当然、最低限の列のみを取得
するようにしますが。


[ メッセージ編集済み 編集者: maru 編集日時 2006-05-26 12:54 ]
ハルシオン
常連さん
会議室デビュー日: 2005/03/29
投稿数: 24
投稿日時: 2006-05-26 12:55
皆様、早速のご回答ありがとうございます。

引用:

まいるどきゃっとさんの書き込み

皆さんが指摘している通りで、「列名を全て」の意味をもう一度その先輩に聞いてみたほうがいいと思います。



言葉が足りず、申し訳ありません。

現在のSQLは全行全列をまるごと取得することが必要なため、
[SELECT * FROM テーブル名(以降WHERE句等なし)]
という記述をしております。

おそらく先輩も、
「全列必要なSQLでも、あえて全列分の列名を列挙するべきだ」
という意味で私にそう助言してくれたのだと思います。

前提となる文章が抜けていて大変申し訳ないです。

引用:

Penguinさんの書き込みより:

「select *」でも「select 全ての列名」でも全ての列を選択することには変わりがないので、同じでは?



引用:

vincentさんの書き込みより:

例えばTABLE1(A, B, C, D, E)という表があったとして、
これに対するSELECTを「SELECT * FROM TABLE1」と書こうが
「SELECT A,B,C,D,E FROM TABLE1」と書こうが、この場合は
取得するデータ量は同じなのでレスポンスも似たような
ものになります。
(オプティマイザの示す実行プランもほぼ同等になるでしょう)



やはり単純なSQLの場合はレスポンスに変わりは無いのですね。。。
ただ、その他もろもろの理由があり、「SELECT * FROM 〜」は
よろしくないと。。。ふむふむ。

引用:

ueさんの書き込みより:

OracleとSQL Server、チューニングの違いを知る
http://www.atmarkit.co.jp/fdb/rensai/rdbmsarc05/rdbmsarc05_1.html#3



大変ありがたい情報でした!ありがとうございます。
「同じSQLでも製品(Oracle/SQLServer)により挙動が異なる」ことがある、という部分
まで全く意識をせずにSQL文を書いていました。
下のURLの英文も、英語を恐れず翻訳して読んでみます。
ありがとうございます。


引用:

じゃんぬさんの書き込みより:

可読性というより保守性じゃないんですか?



そうかもしれないです。
「*」だとテーブルにどんな列があって、どんな列取得してるかわからないから
→「読みにくい!」→「保守しにくい!」
ということでしょうか。
確かに保守性という言葉のほうがピンと来ます。


引用:

まいるどきゃっとさんの書き込みより:

WHERE句があれば取得列とインデックスの有無で実行プランが大きく
変わります。データ抽出速度も違いますし、データ取得そのものについても
直接アクセスしないでカバリングインデックスで済む場合があります。


早速やってみます!

引用:

NAOさんの書き込みより:

*でやっても全列記述してもレスポンスだけを気にするならば
全く意味の無い事です。

実際さんもクエリープランで確かめているわけでしょう?

事実を突きつけてあげたほうが良いと思います


確かに!!
レスポンス、という点では先輩は間違っていたっww
ただ、「SELECT * FROM 〜」という記述方法は色々な弊害がありそうなので
<b>レスポンス対策ではない</b>理由から、列名を全て記述したほうがよいか
先輩にお伺いを立てることにします。

引用:

明智重蔵さんの書き込みより:

DataTableを作った時に余計な列まで作る
ネットワークを流れるデータが増える


DataTableというのは.NETのDataTableとはちがいますよね?
不勉強ですみません。
RecordSet、というような解釈でよいでしょうか?
ちょっと調べてみます。


引用:

maruさんの書き込みより:
私は列項目が多いテーブルで、項目数の半分以上をSelectして、1回のアクセスに数行
〜数十行程度取得して、体感速度的に問題ないようなものに関しては、保守性のことを
考慮して * をよく使います。

ダラダラと列名を列挙するのはゾッとします。


やはりそうですね。
コードがムダに長くなるので、私も[*]としていました。
やはり、使い方次第、ということでしょうか。


皆様、色々ご意見ありがとうございます。

とりあえず、皆様から頂いた情報&SQLの実行プラン結果を
携えて先輩に『結果報告』したいと思います。

生意気な!と鼻息荒げて怒られるかもしれませんが、
いって来ます!
ありがとうございました。

#昼以降に結果を報告いたします。



まいるどきゃっと
大ベテラン
会議室デビュー日: 2004/08/12
投稿数: 135
お住まい・勤務地: 群馬
投稿日時: 2006-05-26 13:12
保守性を考えた場合に「SELECT * 〜」がありえないのは、可読性もそうですが、ソースとテーブルで列の順番を合わせる必要が出てくるという理由もあります。

DBにもよるかもしれませんが、ソースが列A、B、CがABCの順番で返ってくることを前提として書かれている場合、テーブルの列の定義がACBになっていると、Bを受けるはずの変数にCの、Cを受けるはずの変数にBの値が入ることになります。

これが案外あなどれなくて、以前テスト環境で問題なかったから本番リリースしたら本番データをぶっ壊して初めてこのバグに気づいた、というシャレにならない事も起きてます。

だったらソースとテーブルの定義を合わせればいいじゃないかという意見もあるでしょうが、そんな手間かけるくらいなら最初から列名を記述しておくほうが建設的だと思います。

[ メッセージ編集済み 編集者: まいるどきゃっと 編集日時 2006-05-26 13:14 ]
teto
ベテラン
会議室デビュー日: 2002/07/31
投稿数: 61
投稿日時: 2006-05-26 13:27
引用:

DBにもよるかもしれませんが、ソースが列A、B、CがABCの順番で返ってくることを前提として書かれている場合、テーブルの列の定義がACBになっていると、Bを受けるはずの変数にCの、Cを受けるはずの変数にBの値が入ることになります



これは本件とは別かと。
取得列の順に依存する実装であれば「*」を使用するのはバグでしょう。
鎌田
常連さん
会議室デビュー日: 2003/09/23
投稿数: 45
投稿日時: 2006-05-26 13:34
>現在のSQLは全行全列をまるごと取得することが必要なため、

なにげに凶悪な話が出ていますが、そのテーブルのデータ件数は少ないのでしょうか。
ハルシオン
常連さん
会議室デビュー日: 2005/03/29
投稿数: 24
投稿日時: 2006-05-29 10:27
おはようございます。

先日は色々と教えていただきありがとうございます。
『WHERE文を含まない「SELECT * FROM テーブル名」でレスポンス低下はない!』
と先輩に告げ、色々と証拠物件を挙げたところ、
「ふーんそうなんだ」で終わってしまいました。
かなりほっとしておりますが、これから先輩の逆襲が始まりそうな気もします。

ただ、先輩が拗ねてしまうと今後やりづらいという理由と、
皆様にご指摘いただいたように保守等の面から、全列名を
記載する方法に修正いたしました。

引用:

鎌田 さんの書き込み

>現在のSQLは全行全列をまるごと取得することが必要なため、

なにげに凶悪な話が出ていますが、そのテーブルのデータ件数は少ないのでしょうか。



確かに件数によっては凶悪なお話ですね!
今回は月次でデータが増えるテーブルなので、最大でも12件のデータしか
保持しない予定です。
ご心配おかけしました。

引用:

まいるどきゃっと さんの書き込み

保守性を考えた場合に「SELECT * 〜」がありえないのは、可読性もそうですが、ソースとテーブルで列の順番を合わせる必要が出てくるという理由もあります。

DBにもよるかもしれませんが、ソースが列A、B、CがABCの順番で返ってくることを前提として書かれている場合、テーブルの列の定義がACBになっていると、Bを受けるはずの変数にCの、Cを受けるはずの変数にBの値が入ることになります。



確かにそうですね。
意識して取得列の列名を記述することで防げるバグです。
どのみちテーブルレイアウトを変更する際は、一度全てのソースを見直す必要が出てくると思うので、

引用:

teto さんの書き込み

取得列の順に依存する実装であれば「*」を使用するのはバグでしょう。



無駄なバグを出さないためにも全列指定することにいたします。

でも、「SELECT * FROM 〜」で記述することが不自然ではないパターンも
存在しそうですね。

今後とも勉強させていただきます。
重ね重ね、御礼申し上げます。
ありがとうございました。

スキルアップ/キャリアアップ(JOB@IT)