SQL Azure Team Blog

SELECT * AND SQL Azure – SQL Azure Team Blog – Site Home – MSDN Blogsを簡単に翻訳したエントリーです。

全ての良いDBAと開発者は、特別必要が無ければ全てのレスを返すクエリを発行すべきで無いことを知っています。

SELECT * FROM [Table]

SELECT文では、必要な列のみを返すようにします。SELECT *を使用すると余計なページングの原因となります。RFIDルックアップ、不必要なテーブルロック、カバードインデックスの作成意図の無効化等が発生します。結果としてパフォーマンスに悪影響が出ます。

さらに、SQL Azureには SELECT *を使用すべきでない理由があります。データ転送料に応じた課金を行うからです。もし、(Windows Azureアプリケーションではない)データセンターの外から使用する場合、クエリによって発生するデータ転送量に応じて料金を支払います。もし使用しない列も要求すると、使用していないデータの転送量にまで支払うことになります。

SELECT *クエリを削除することをあなたのTO-DOリストにあるのなら、SQL Azureですばらしい体験ができるでしょう。

 

(コメント欄より抜粋)

Entity FrameworkのようなORMでも、SELECT *は生成させるべきで無い。しかし、「Oraders.Where」や「.OrderBy」などを使用しても、特別にSELECT句「.select」を指定しない場合、SELECT *が生成されてしまいます。

SQL Azure Team Blog

この投稿は、SELECT INTO With SQL Azureを意訳したものです。随時、意味がとりやすいよう手を加えていますので、オリジナルと文意が変わっている箇所があるかもしれません。

SQL Azureでは、(データを入れる際に)すべてのテーブルにクラスター化インデックスが必要なので、SELECT INTO文でのテーブル作成、クラスター化インデックスの作成をサポートしていません。
SQL Azureへの移行を計画する場合、SELECT INTO文の代わりにテーブルを作成するコードを準備する必要があります。クラスター化インデックスが必要の無い一時テーブルを使用するか、通常のテーブルを使用するかで対応します。

実験するために、簡単に移行元のサンプルデータを用意します。

CREATE TABLE Source (Id int NOT NULL IDENTITY, [Name] nvarchar(max), [Color] nvarchar(10),  
CONSTRAINT [PK_Source] PRIMARY KEY CLUSTERED 
(
      [Id] ASC
))
      
INSERT INTO Source([Name], [Color]) VALUES ('Shirt','Red')
INSERT INTO Source([Name], [Color]) VALUES ('Pants','Red')
INSERT INTO Source([Name], [Color]) VALUES ('Tie','Pink')

試しにSELECT INTOを使用してみます。

クラスター化インデックスを必要としない一時テーブルにSELECT INTOを使用します。

SELECT *
INTO #Destination
FROM Source
WHERE [Color] LIKE 'Red'
-- Do Something

--DROP TABLE #Destination

このSQLをSQL Azureに使用すると、クラスター化インデックスを必要としない一時テーブルでも失敗し、エラーが表示されます。

メッセージ 40510, レベル 15, 状態 2, 行 1

Statement ‘SELECT INTO’ is not supported in this version of SQL Server.

次に、あらかじめクラスター化インデックスが無い一時テーブルを作成した状態で、SELECT INTO文を使用してみます。

CREATE TABLE #Destination (Id int NOT NULL, [Name] nvarchar(max), [Color] nvarchar(10))

INSERT INTO #Destination(Id, [Name], [Color])
SELECT Id, [Name], [Color]
FROM Source
WHERE [Color] LIKE 'Red';

-- Do Something

DROP TABLE #Destination

結果は、2行正しく処理されます。

まとめ

SELECT INTO文を使用する場合は、下のどちらかを選択しなければなりません。

  • 予め移行先のテーブルを準備し、クラスター化インデックスを作成しておく
  • 予め移行先のテーブルとして、(クラスター化インデックスが必要のない)一時テーブルを作成しておく

SQL Azure Team Blog

情報源:Clustered Indexes and SQL Azure – SQL Azure Team Blog – Site Home – MSDN Blogsを簡単に翻訳したエントリーです。

SQL Azureの基本に集中した新しいシリーズ連載を始め、SQL Azureを使用したアプリケーションを開発したり、マイグレーションする為の詳細な情報を提供します。

SQL Serverとは違って、SQL Azureは全てのテーブルにクラスターインデックスが必要です。クラスターインデックスは通常、プライマリキーに指定した列に作成されます。クラスタインデックスは、キーの値に応じて行を並べ替え格納します。一つの条件に従って行を並べ替えなければならないので、クラスターインデックスは、一つのテーブルに一つしか作成できません。

クラスターインデックスを持つシンプルなテーブルの例

CREATE TABLE Source (Id int NOT NULL IDENTITY, [Name] nvarchar(max), 
CONSTRAINT [PK_Source] PRIMARY KEY CLUSTERED 
(
      [Id] ASC
))

SQL Azureに、クラスターインデックスの無いテーブルを作成することができますが、そのテーブルにデータを追加しようとすると次のエラーが発生します。

Msg 40054, Level 16, State 1, Line 2

Tables without a clustered index are not supported in this version of SQL Server. Please create a clustered index and try again.

SQL Azureはヒープテーブルを許可していません。ヒープテーブルの定義は、クラスタインデックスの無いテーブルのことです。SQL Serverのインデックスに関する追加情報は、MSDN上のドキュメントを確認してください。

 

一時テーブル

 

データベース上の全ての通常のテーブルは、このルールに従いますが、一時テーブルの場合はルールに当てはまりません。SQL Serverで一時テーブルを作成したのと同様に、SQL Azureにも一時テーブルを作成できます。

CREATE TABLE #Destination (Id int NOT NULL, [Name] nvarchar(max))
-- Do Something
DROP TABLE #Destination