SELECT *
は、特に必要なSELECT
列の方が効率的であるため、SQLコマンドを記述するときに使用することは一般的に悪い習慣です。
テーブルのすべての列をSELECT
する必要がある場合は、使用する必要があります
SELECT * FROM TABLE
または
SELECT column1, colum2, column3, etc. FROM TABLE
この場合、効率は本当に重要ですか? SELECT *
は、すべてのデータが本当に必要な場合、内部的に最適化されますが、データベースを実際に理解していない状態でこれを言っています。
この場合のベストプラクティスが何であるかを知りたいです。
PDATE:私はおそらく、私が本当にwant_SELECT *
は、新しい列が追加された場合でも、すべての列を常に取得する必要があることがわかっている1つのテーブルからデータを選択するときです。
しかし、私が見た反応を考えると、これはまだ悪い考えのように思え、SELECT *
は、私が今まで考えていたより多くの技術的な理由で使用すべきではありません。
特定の列を選択するほうが良い理由の1つは、テーブルデータを照会するのではなく、SQL Serverがインデックスからデータにアクセスできる可能性が高まることです。
ここに私が書いた投稿があります: 選択クエリが悪いインデックスカバレッジである本当の理由
また、データを消費するコードは、将来テーブルスキーマに加えた変更に関係なく、同じデータ構造を取得するため、変更しても脆弱ではありません。
your指定するとareすべての列を選択すると、ほとんど違いはありません現時点。ただし、データベーススキーマが変更されることを認識してください。 SELECT *
コードに新しいデータを使用または表示する準備ができていない場合でも、テーブルに新しい列を追加します。これは、予期しないパフォーマンスと機能の変更にシステムをさらしていることを意味します。
これを軽微な費用として却下することもできますが、不要な列は次のとおりであることに注意してください。
アイテム#1には、潜在的なカバーインデックスの削除、データページのロード(およびサーバーキャッシュのスラッシング)の発生、行/ページ/テーブルロックの回避などの隠れたコストが含まれます。
列と*
および潜在的な節約は次のとおりです。
項目1の現実は、コードを追加/変更して、とにかく追加する可能性のある新しい列を使用することです。
項目2については、異なるパケットサイズまたはネットワークパケット数にプッシュするのに十分な差はめったにありません。 SQLステートメントの送信時間が主な問題になるポイントに到達した場合、おそらく最初にステートメントの割合を減らす必要があります。
アイテム3の場合、*
はとにかく発生する必要があります。つまり、とにかくテーブルスキーマを調べます。現実的には、列はスキーマに対して検証する必要があるため、列のリストには同じコストがかかります。言い換えれば、これは完全な洗浄です。
アイテム4では、特定の列を指定すると、クエリプランキャッシュが大きくなる可能性がありますが、異なる列のセット(指定したものではない)を処理する場合はonlyになります。この場合、必要に応じて異なるプランが必要なため、do want異なるキャッシュエントリを使用します。
そのため、質問を指定した方法により、最終的にスキーマが変更された場合の問題の回復力が低下します。このスキーマをROM(それが起こる))に書き込む場合、*
は完全に受け入れられます。
ただし、私の一般的なガイドラインは、必要な列のみを選択することです。つまり、時々すべてを求めているように見えますが、DBAとスキーマの進化は、いくつかの新しい列がクエリに大きな影響を与える可能性があります。
私のアドバイスは、特定の列を常に選択するにすることです。繰り返し行うことで上手くいくことを忘れないでください。
コードを変更せずにスキーマが変更される理由を知りたい場合は、監査ログ、有効/有効期限、およびコンプライアンスの問題のためにDBAが体系的に追加するその他の類似事項の観点から考えてください。不十分な変更のもう1つの原因は、システムまたはユーザー定義フィールドの他の場所でのパフォーマンスの非正規化です。
必要な列のみを選択する必要があります。すべての列が必要な場合でも、SQLサーバーがシステムテーブルに列を照会する必要がないように、列名をリストすることをお勧めします。
また、誰かがテーブルに列を追加すると、アプリケーションが壊れる可能性があります。プログラムは予期しない列を取得し、それらの処理方法を知らない可能性があります。
これとは別に、テーブルにバイナリ列がある場合、クエリははるかに遅くなり、より多くのネットワークリソースを使用します。
select *
は悪いことです。
最も重要な実際的な理由は、列が返される順序をユーザーに魔法のように強制させることです。明示的にする方が良いです。これはまた、テーブルの変更からあなたを守ります。
使用している列名が変更された場合、すでに存在しない(または名前が変更された)列を使用しようとするよりも、早期に(SQL呼び出しの時点で)キャッチする方が適切です。 )
列名をリストすると、コードがはるかに自己文書化され、おそらく読みやすくなります。
ネットワーク経由で転送する場合(または転送しない場合でも)、不要な列は無駄になります。
列リストの指定は通常が最適なオプションです。なぜなら、誰かがテーブルに列を追加/挿入してもアプリケーションは影響を受けないからです。
サーバーの場合、列名の指定は間違いなく高速です。しかし、もし
その後、SELECT *を使用することをお勧めします。私たちのフレームワークでは、SELECT *を多用することで、新しいWebサイト管理コンテンツフィールドをテーブルに導入し、CMSのすべての利点(バージョン管理、ワークフロー/承認など)を提供できます。数十点ではなく、数点です。
DBの達人がこれを嫌うことはわかっています-先に進み、投票してください-しかし、私の世界では、開発者の時間は少なく、CPUサイクルは豊富です。
SELECT *は、クエリがネットワーク経由で送信されない場合でも悪い習慣です。
もちろん、これはすべて小さくてシンプルなシステムにとっては重要ではありません。
パフォーマンスに関しては、特定の列を使用したSELECTの方が高速です(すべてのデータを読み込む必要はありません)。クエリが実際にすべての列を使用する場合、明示的なパラメーターを使用したSELECTが引き続き推奨されます。速度の違いは基本的に気付かれず、ほぼ一定時間です。ある日、スキーマが変更されます。これは、これによる問題を防ぐための良い保険です。
ここまで多くの正当な理由がここで回答されましたが、言及されていない別の理由があります。
列に明示的に名前を付けると、今後のメンテナンスに役立ちます。ある時点で、変更またはトラブルシューティングを行い、「その列はどこで使用されているのか」を自問することになります。
名前が明示的にリストされている場合、その列へのすべての参照を見つけるには、すべてのストアドプロシージャ、ビューなどを介して-簡単です。 DBスキーマのCREATEスクリプトをダンプし、それをテキスト検索するだけです。
本当に必要なフィールドのみを選択し、必要な数だけを選択する必要があります。
SELECT Field1, Field2 FROM SomeTable WHERE --(constraints)
データベースの外部では、動的クエリはインジェクション攻撃や不正なデータのリスクを実行します。通常、これはストアドプロシージャまたはパラメーター化されたクエリを使用して実行されます。また、(実際にはそれほど問題ではありませんが)サーバーは、動的クエリが実行されるたびに実行計画を生成する必要があります。
「select *」の問題は、本当に必要のないデータを持ち込む可能性です。実際のデータベースクエリ中に、選択した列が実際に計算に追加されることはありません。本当に「重い」のは、クライアントへのデータ転送であり、実際に必要のない列は、ネットワーク帯域幅を浪費し、クエリが返されるのを待っている時間を増やすだけです。
「select * ...」からもたらされたすべての列を使用しても、それは今のところです。将来、テーブル/ビューのレイアウトを変更し、列を追加すると、それらが不要な場合でも選択に追加し始めます。
「select *」ステートメントが悪いもう1つのポイントは、ビューの作成です。 「select *」を使用してビューを作成し、後でテーブルに列を追加すると、ビュー定義と返されるデータが一致しなくなり、ビューを再コンパイルして再度機能させる必要があります。
「select *」を書くのは魅力的だということを知っています。なぜなら、クエリのすべてのフィールドを手動で指定するのは本当に好きではないからです。しかし、システムが進化し始めたら、この余分な時間を費やす価値があることがわかります。ビューのバグを削除したり、アプリを最適化したりするのに多くの時間と労力を費やすのではなく、フィールドを指定することの努力.
明示的に列をリストすることはパフォーマンスに役立ちますが、夢中にならないでください。
したがって、すべてのデータを使用する場合は、簡単にするためにSELECT *を試してください(多くの列があり、JOIN ...クエリを実行すると想像がつかない場合があります)。その後-測定。列名が明示的にリストされているクエリと比較してください。
パフォーマンスについて推測しないでください測定してください!
明示的なリストは、ビッグデータ(投稿または記事の本文など)を含む列があり、特定のクエリでは必要ない場合に最も役立ちます。その後、応答に返さないことで、DBサーバーは時間、帯域幅、ディスクスループットを節約できます。クエリ結果も小さくなり、クエリキャッシュに適しています。
列をプルするためにSQL Serverが列を検索する必要がないため、列を明確に定義します。列を定義すると、SQLはそのステップをスキップできます。
必要な列を指定することは常に適切です。一度考えれば、SQLはクエリのたびに「wtf is *」と考える必要はありません。その上、誰かが後でクエリで実際に必要としない列をテーブルに追加する場合があります。その場合は、すべての列を指定することをお勧めします。
*または列を使用する場合、選択は(速度の点で)同様に効率的です。
違いは、速度ではなくメモリに関するものです。複数の列を選択する場合、SQL Serverは、クエリを提供するために、要求したすべての列のすべてのデータを含むメモリスペースを割り当てる必要があります。
パフォーマンスの点で重要なのは、実行計画です。実行計画は、WHERE句と、JOIN、OUTER JOINなどの数に大きく依存します。
質問にはSELECT *を使用してください。すべての列が必要な場合、パフォーマンスの違いはありません。
結果は大きすぎます。結果を生成してSQLエンジンからクライアントに送信するのは遅いです。
一般的なプログラミング環境であるクライアント側は、行数が膨大になる可能性があるため(たとえば数千万行)、結果(たとえば、WHERE句、ORDER句)をフィルタリングおよび処理するように設計されていません。
また、アプリケーションで取得する予定の各列に名前を付けると、列が(任意の順序で)存在する限り、誰かがテーブルを変更してもアプリケーションが壊れることはありません。
すべてのフィールドのデータを取得する必要がある場合に限り、明示的なフィールド名を使用するほうが*よりも高速ではありません。
クライアントソフトウェアは、返されるフィールドの順序に依存してはならないため、これもナンセンスです。
また、*を使用してすべてのフィールドを取得する必要がある可能性はありますが、どのフィールドが存在するのかまだわからないため(非常に動的なデータベース構造を考えてください)。
明示的なフィールド名を使用することのもう1つの欠点は、フィールド名が多数あり、それらが長い場合、コードやクエリログの読み取りが難しくなることです。
したがって、ルールは次のとおりです。すべてのフィールドが必要な場合は*を使用し、サブセットのみが必要な場合は明示的に名前を付けます。
DBサーバーのバージョンに依存しますが、最新バージョンのSQLはどちらの方法でもプランをキャッシュできます。私はあなたのデータアクセスコードで最も維持しやすいものなら何でもいいと思います。
希望する列を正確に入力する方がよい理由の1つは、テーブル構造の将来の変更の可能性があるためです。
インデックスベースのアプローチを使用して手動でデータを読み込み、クエリの結果をデータ構造に入力する場合、将来、列を追加/削除するときに、問題の原因を突き止めようとする頭痛の種になります。
より速いものについては、他の人の専門知識のために延期します。
また、定義による内部結合がある場合は、結合列のデータが繰り返されるため、すべての列が必要なわけではないことに注意してください。
SQlサーバーで列を一覧表示するのは難しいことではなく、時間がかかることでもありません。オブジェクトブラウザからドラッグするだけです(Wordの列からドラッグすることで、すべてを一度に取得できます)。システムに永続的なパフォーマンスヒットを与えるため(これによりインデックスの使用が削減され、不要なデータをネットワーク経由で送信するとコストがかかるため)、データベースの変更時に予期しない問題が発生する可能性が高くなります(列が追加されることがあります)たとえば、ユーザーに表示させたくない場合は、1分未満の開発時間を節約するだけで、近視眼的で専門的ではありません。
上記の皆が言ったことに加えて:
読みやすい保守可能なコードを探しているなら、次のようなことをしてください:
SELECT foo、bar FROMウィジェット。
即座に読み取り可能で、意図を示します。あなたがその電話をかけるなら、あなたは何を得ているかを知っています。ウィジェットの列がfooとbarのみの場合、*を選択すると、戻ってくるものについて考え、順序が正しくマッピングされていることを確認する必要があることを意味します。そして、バーを押すと、ワイルドカードを照会し、返されたものの一部のみを使用するときにコードが乱雑になります。
SELECT *は、列数などのメタデータを取得する場合に必要です。
他の人が言ったことに追加するために、選択しているすべての列がインデックスに含まれている場合、結果セットはSQLから追加のデータを検索する代わりにインデックスから取得されます。
ほとんどの問題と同様に、それは何を達成したいかによって異なります。任意のテーブルのすべての列を許可するdbグリッドを作成する場合は、「選択*」が答えです。ただし、特定の列のみが必要で、クエリへの列の追加または削除がまれにしか行われない場合は、それらを個別に指定します。
また、サーバーから転送するデータの量にも依存します。列の1つがメモ、グラフィック、blobなどとして定義されていて、その列が必要ない場合は、「選択*」を使用しないか、または大量のデータを取得する必要がありますあなたのパフォーマンスが低下する可能性があります。
効率が重要かどうかは、運用データセットのサイズ(およびその成長率)に大きく依存します。データセットがそれほど大きくなく、それほど速く成長しない場合、個々の列を選択することによるパフォーマンス上の利点はあまりありません。
データセットが大きくなり、データの成長速度が速くなると、パフォーマンス上の利点がますます重要になります。
違いがあるかどうかをグラフィカルに確認するには、クエリアナライザーを使用して、SELECT *および同等のSELECT col1、col2などのクエリ実行プランを表示することをお勧めします。さまざまなボリュームのテストデータを生成して、タイミングを確認することもできます。
これに非難されますが、select *を実行します。ほとんどすべてのデータが、必要な値を複数のテーブルから単一のアクセスしやすいビューに事前結合するSQL Serverビューから取得されるためです。
次に、新しいフィールドが基になるテーブルに追加されても変更されないビューのすべての列が必要です。これには、データの出所を変更できるという利点もあります。ビューのFieldAは一度計算された後、静的になるように変更できます。いずれにしても、ViewはFieldAを提供します。
この利点は、データレイヤーがデータセットを取得できることです。次に、それらをBLに渡し、BLからオブジェクトを作成できます。私のメインアプリは、オブジェクトを認識して対話するだけです。データ行が渡されると、オブジェクトが自己作成することもできます。
もちろん、私が唯一の開発者なので、それも役立ちます:)
毎回選択する列を絶対に定義します。そうする理由はなく、パフォーマンスを向上させるだけの価値はあります。
彼らは「SELECT *」のオプションを決して与えてはいけません。
すべての列が必要な場合は、SELECT *を使用しますが、結果を使用するときにインデックスではなく名前でアクセスするため、順序が変更される可能性があることに注意してください。
リストを取得する方法についてのコメントは無視します-名前付き列を解析および検証する可能性は、処理時間と同じかそれ以上ではありません。時期尚早に最適化しないでください;-)
2つの主な違いは、やり取りされるデータの量です。 「select *」および「select col1、...、colN」の結果、DBエンジンが実行する相対的な作業量が同じになるという点で、時間差に関する引数には根本的な欠陥があります。ただし、行ごとに15列を送信する場合と行ごとに5列を送信する場合は、10列の違いがあります。
実行効率に関しては、大きな違いはありません。しかし、プログラマーの効率のために、フィールドの名前を書きます。
列を指定するのにもっと時間がかかると考える人がいるようです。オブジェクトブラウザから列リストをドラッグできるため、クエリで列を指定するのに余分な時間がかかる場合があります(列が多く、別の行に配置するのに時間がかかる場合)。なぜ人々はそれがそんなに時間がかかると思いますか?
スキーマが変更され、追加の列が不要な場合に備えて、必要な列を指定することを常にお勧めします。
さらに、列名をテーブル名で修飾します。これは、クエリに結合が含まれる場合に重要です。テーブルの資格がないと、どの列がどのテーブルから来たのかを覚えるのが難しくなる可能性があり、同様の名前の列を他のテーブルの1つに追加するとクエリが壊れる可能性があります。
パフォーマンスに関しては、どちらも等しいというコメントを見ました。しかし、ユーザビリティの側面には、いくつかの+と-があります
クエリで(select *)を使用し、誰かがテーブルを変更し、前のクエリに必要のない新しいフィールドを追加する場合、それは不必要なオーバーヘッドです。そして、新しく追加されたフィールドがブロブまたは画像フィールドの場合はどうなりますか?その場合、クエリの応答時間は非常に遅くなります。
一方、(select col1、col2、..)を使用し、テーブルが変更されて新しいフィールドが追加され、それらのフィールドが結果セットで必要な場合は、テーブルの変更後に選択クエリを常に編集する必要があります。
ただし、クエリで常にselect col1、col2、...を使用し、後でテーブルが変更された場合はクエリを変更することをお勧めします。
定義上、少なくとも2つのフィールドに同じデータが含まれるベカセ結合がある場合、パフォーマンスのためにselect *を使用しないことが特に重要です。データベースサーバーからアプリケーションまたはWebサーバーに不要なデータを送信するネットワークリソースを無駄にしたくない。 select *を使用する方が簡単に見えるかもしれませんが、それは悪い習慣です。列名をクエリにドラッグするのは簡単なので、代わりにドラッグしてください。
Select *を使用するときに発生する別の問題は、テーブルの中央に新しいフィールドを追加することを選択するバカがいることです(常に悪い習慣です)。select*を挿入のベースとして使用すると、突然列の順序が間違っていると、社会保障番号を謝礼金に挿入しようとする可能性があります(話者が非ランダムな例を選ぶために支払われるかもしれないお金の量)。これはデータの整合性にとって非常に悪いことです。選択が挿入ではない場合でも、データがレポートまたはWebページで突然ウェアリングされた順序になっていると、顧客にとって見た目が悪くなります。
Select *を使用する場合、列リストを使用するよりも望ましい状況はないと思います。保守が簡単だと思うかもしれませんが、実際にはそうではなく、不要なフィールドがテーブルに追加されると、理由もなくアプリケーションが遅くなります。また、列リストを使用していた場合に破損しないものを修正するという問題に直面する必要があるため、列を追加しないことで節約できる時間は、これを行うために使い果たされます。
ちょっと、実用的にしてください。プロトタイピング時にはselect *を使用し、実装およびデプロイ時には特定の列を選択します。実行計画の観点から見ると、両方とも最新のシステムでは比較的同一です。ただし、特定の列を選択すると、ディスクから取得し、メモリに保存し、ネットワーク経由で送信する必要があるデータの量が制限されます。
最終的には、特定の列を選択することが最善の計画です。
また、変更を念頭に置いてください。今日、Select *は必要な列のみを選択しますが、明日、追加したばかりのvarbinary(MAX)列も選択せずに選択することがあります。昨日のテーブルで。
どちらが速いか考えてみましょう。必要なデータのみを選択できる場合は、より高速です。ただし、テストでは、すべてのデータをプルして、ビジネスニーズに基づいてどのデータを除外できるかを判断できます。
SELECT *が保守目的に適している場合もありますが、一般的には避ける必要があります。
これらは、ビューやストアドプロシージャのような特殊なケースであり、テーブルを使用するすべてのビューやストアドプロシージャを変更することなく、基礎となるテーブルの変更を伝播します。それでも、2つのビューが結合されている場合のように、これは問題自体を引き起こす可能性があります。基になるテーブルが1つ変更され、両方のテーブルに同じ名前の列があるため、ビューがあいまいになりました。 (これは、すべての列をテーブルプレフィックスで修飾しない場合に発生する可能性があります)。プレフィックスがあっても、次のような構造がある場合:
SELECT A .、B。-クライアントが正しいフィールドを選択するのが困難になるという問題が発生する可能性があります。
一般に、意識的な設計決定を下し、関連するリスクが低いと考えている場合を除き、SELECT *は使用しません。
SELECT *
mightすべての列が実際に必要な場合は問題ありませんが、それらはすべて個別にリストする必要があります。アプリとDBが同じサーバーまたはネットワーク上にある場合でも、テーブルからすべての行を選択すべきではありません。すべての行を転送するには、特に行の数が増えると時間がかかります。結果をフィルタリングする少なくとも1つのwhere句が必要です。また、結果をページングして、表示する必要がある行のサブセットのみを選択する必要があります。必要なデータのサブセットのクエリとページングを支援するために使用しているアプリの言語に応じて、いくつかのORMツールが存在します。たとえば、.NET Linq to SQL、Entity Framework、およびnHibernateはすべてこれに役立ちます。
特定のフィールド名を使用して、誰かがあなたのテーブルを変更しても、予期しない結果が得られないようにしてください。件名:挿入時にフィールド名を常に指定するため、後で列を追加する必要がある場合、本番リリースでプログラムを修正してデータベースを同時に変更する必要はありません。
速度が心配な場合は、準備済みステートメントを使用してください。そうでなければ、変化はあなたがあなた自身から守るものであるという不法行為です。
/アラン
他の開発者がコードを操作する可能性が高い場合、またはデータベースが変更される可能性がある場合、列名のリストは特に重要であり、常に一貫したデータを取得できます。
これは古い投稿ですが、まだ有効です。参考のために、私は非常に複雑なクエリで構成されています:
Select *を使用してクエリを実行すると、平均2869msかかります。 Selectを使用してクエリを実行すると、平均1513msかかります。
返される行の合計は13,949です。
列名を選択すると、Selectよりもパフォーマンスが向上することは間違いありません*
(sqlplusプロンプトやdb管理ツールなどで)DBを直接クエリする場合は、一般にselect *で問題ありません。すべての列を書き出す手間が省けます。
一方、アプリケーションコードでは、列を列挙するのが最適です。これにはいくつかの利点があります。
まあ、それはあなたのメトリックと目的に本当に依存します:
経験則として、すべての列を選択する必要がある場合、特別な理由がない限り「select *」を使用します(さらに、多くの列があるテーブルではより高速だと思います)
最後になりましたが、テーブルの列を追加または削除して、コードまたはそのメンテナンスにどのように影響を与えたいですか?