SQL Server 2012(または2005年以降のすべてのバージョン)ではSELECT *...
、クエリの最上位のSELECTステートメントでパフォーマンスの問題が発生する可能性があります。
ビュー(*)で、サブクエリで、EXIST句では、CTEの中で、またして問題ではないが、それはそうSELECT COUNT(*)..
、これはOracleのためにも、おそらく真実であることに注意してください、とDB2、およびなどなど多分 POSTGRES(ないように注意してください) 、しかし、MySqlの多くの場合、依然として問題である可能性が非常に高いです。
なぜ(そして、なぜそれがトップレベルSELECTで問題になる可能性がまだある)を理解するには、それが今まで使用しているためであるという問題であった理由を理解することが役に立つSELECT *..
手段は、「すべての列を返します」。一般に、これは本当に必要なデータよりもはるかに多くのデータを返します。これにより、ディスクとネットワークの両方で、明らかに多くのIOが発生する可能性があります。
あまり明らかではないのは、これによりSQLオプティマイザーが使用できるインデックスとクエリプランが制限されることです。これは、最終的にすべてのデータ列を返す必要があることがわかっているためです。特定の列のみが必要であることが事前にわかっている場合、多くの場合、それらの列のみを持つインデックスを利用することで、より効率的なクエリプランを使用できます。幸いなことに、これを事前に知る方法があります。これは、列リストで必要な列を明示的に指定するためのものです。ただし、「*」を使用する場合は、「すべてを提供してください。必要なものがわかります」ということを支持して、これを忘れています。
はい、すべての列の処理に追加のCPUとメモリの使用もありますが、これらの2つのことと比較すると、ほとんど常にマイナーです:不要な列に必要なディスクとネットワーク帯域幅の大幅な増加と、すべての列を含める必要があるため、最適化されたクエリプラン。
それで何が変わったのですか?基本的に、SQLオプティマイザーは、クエリの上位レベルで実際に列を使用する場合に下位レベルのサブクエリで把握できることを意味する「列最適化」と呼ばれる機能をうまく組み込みました。
これの結果は、クエリの下位/内部レベルで「SELECT * ..」を使用しても問題にならないということです。代わりに、実際に重要なのは、最上位のSELECTの列リストにあるものです。SELECT *..
最上部で使用しない限り、もう一度、すべての列が必要であると仮定する必要があるため、列の最適化を効果的に使用できません。
(*-ビューに*
は、「*」を使用したときに列リストの変更が常に登録されない、別の小さなバインディング問題があることに注意してください。これに対処する他の方法があり、パフォーマンスに影響しません。)