都内で働くSEの技術的なひとりごと / Technical soliloquy of System Engineer working in Tokyo

都内でサラリーマンやってます。SQL Server を中心とした (2023年からは Azure も。) マイクロソフト系(たまに、OSS系などマイクロソフト以外の技術も...)の技術的なことについて書いています。日々の仕事の中で、気になったことを技術要素関係なく気まぐれに選んでいるので記事内容は開発言語、インフラ等ばらばらです。なお、当ブログで発信、発言は私個人のものであり、所属する組織、企業、団体等とは何のかかわりもございません。ブログの内容もきちんと検証して使用してください。英語の勉強のため、英語の

SQL Database を使って、データベースのアクセススピードの速度比較をしてみた

 これも個人レベルの気になったことがあったので、ちょっと実験してみます。データベースへのアクセス速度比較です。内容としては、今更こんなことと思われるレベルなのですが.... 仮想環境上の SQL Server で検証するのも何となくつまらないので、Microsoft Azure、まだ Windows AzureSQL Database を使用して検証してみます。

 Windows Azure のポータルより、SQL データベースを選択し、SQL データベースを作成します、をクリックします。

f:id:koogucc11:20140316095836p:plain

 設定を行い、赤枠の部分をクリックします。

f:id:koogucc11:20140316095912p:plain

 ログイン名およびパスワードをリージョンを設定し、赤枠部分をクリックします。

f:id:koogucc11:20140316095946p:plain

  以上でデータベースの作成は完了です。あとは、下記の内容に従って準備をします。

f:id:koogucc11:20140328192544p:plain

 早速、データベースを参照してみましょう。ログイン画面は Silverlight なんですね。もう懐かしい感じになってしまっていますが....ID, パスワードを入力し、Log On をクリックします。

f:id:koogucc11:20140328192621p:plain

 管理ポータルはそんなに使いやすいものではないですね。SQL Server Management Studio から接続してみましょう。 SQL Server 2014 CTP2 の環境から接続してみます。

f:id:koogucc11:20140316120820p:plain

 赤枠部分のアドレスを SQL Server Management Studio のサーバ名に設定し、 ログインします。

f:id:koogucc11:20140328192831p:plain

f:id:koogucc11:20140328193107p:plain

 サーバに接続が成功すると、下記のように表示されます。下部に 今回接続した SQL データベースが表示されています。

f:id:koogucc11:20140328193335p:plain

 AdventureWorks2012 データベースをごっそり、SQL データベースに移行したいと思います。容量的には問題なさそうですね。では移行してみたいと思います。

f:id:koogucc11:20140328195543p:plain

 赤枠のメニューをクリックします。

f:id:koogucc11:20140328195832p:plain

 SQL データベースに接続し、赤枠の Next をクリックします。

f:id:koogucc11:20140328200119p:plain

 赤枠の Finish をクリックします。

f:id:koogucc11:20140328200415p:plain

 おおっと、SQL Server 2014 はまだ対応されていないんですね。環境を 2012 に変えてみましょう。( 事前に調べずにやってしまうのが、私のいけないところです.... )

f:id:koogucc11:20140328200623p:plain

 ん?2012 にしてもダメですね。あー、そのまま移行ができないんですね。スクリプトを生成しても、そのままは使えないんですね。冷静に考えると当たり前ですね。何使えばいいんでしょうか? BCP コマンドですかね?試してみましょう。

 再度手順を整理して、説明します。(前に示した手順は意味なしです...)

  1. SQL データベース側のレイアウトを作成します。
    主キーは必ず指定してください。インポート時に失敗します。f:id:koogucc11:20140329083107p:plain
  2.  bcp コマンドを実行するのに必要なフォーマットファイルを出力します。下記のコマンドを実行します。

    bcp AdventureWorks2012.Sales.SalesOrderDetail format nul -c -f SalesOrderDetail.fmt -T
  3. bcp コマンドでも、エクスポートのどちらでもよいので、タブ区切りでデータを抽出します。

    f:id:koogucc11:20140329101912p:plain

    f:id:koogucc11:20140329101929p:plain

  4. データを SQL データベースにインポートするため、下記のコマンドを実行します。
    BCP AdventureWorks.Sales.SalesOrderDetail in C:\sales.dat -n -U username@servername -S tcp:servername.database.windows.net -P password -f C:\SalesOrderDetail.fmt

    f:id:koogucc11:20140329102522p:plain

 以上の手順で、SQL Server 2012 → SQL Database のデータ移行が可能です。きちんとデータが移行されたかを確認してみましょう。管理ポータルから、SQL を発行するとデータがきちんと格納されていることがわかります。

f:id:koogucc11:20140329103254p:plain

 今後何かしら改善されていくとは思いますが、SQL データベース への移行は面倒ですね。それでは、検証を行うためのサンプルソースです。( 適当なソースですいません。 )

using System;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Windows.Forms;

namespace DataSetAndDataReader
{
    public partial class Form1 : Form
    {
        string sqlStr = "select * from Sales.SalesOrderDetail Where SalesOrderID = 75121;" +
                        "select * FROM Sales.SalesOrderHeaderSalesReason Where SalesOrderID = 75121";
        string connectStr = "Server=tcp:servername.database.windows.net,1433;Database=AdventureWorks;" +
                            "User ID=userid@servername;Password=password;Trusted_Connection=False;Encrypt=True;Connection Timeout=30;";
        public Form1()
        {
            InitializeComponent();
        }

        private void DataSet_Click(object sender, EventArgs e)
        {
            var sw = new Stopwatch();
            sw.Start();
            using (var cn = new SqlConnection())
            {
                cn.ConnectionString = connectStr;
                cn.Open();

                var da = new SqlDataAdapter(sqlStr, cn);
                var ds = new DataSet("Sales");
                da.Fill(ds, "SalesOrderDetail");
                da.Fill(ds, "SalesOrderHeader");

                var dt1 = ds.Tables["SalesOrderDetail"];
                var dt2 = ds.Tables["SalesOrderHeader"];

                //SalesOrderDetail
                foreach (DataRow dr1 in dt1.Rows)
                {
                    //何かの処理を書く予定。
                }
               
                //SalesOrderHeader
                foreach (DataRow dr2 in dt2.Rows)
                {
                    //何かの処理を書く予定。
                }
            }
            sw.Stop();
            MessageBox.Show(sw.Elapsed.ToString());
        }

        private void DataReader_Click(object sender, EventArgs e)
        {
            var sw = new Stopwatch();
            sw.Start();
            using (var cn = new SqlConnection())
            {
                cn.ConnectionString = connectStr;
                cn.Open();

                var cmd = new SqlCommand();
                cmd.CommandText = sqlStr;
                cmd.Connection = cn;
                var dr = cmd.ExecuteReader();

                while (dr.Read())
                {
                    //何かの処理を書く予定。
                }

                //次の結果を見る。
                dr.NextResult();
                while (dr.Read())
                {
                    //何かの処理を書く予定。
                }

                dr.Close();
                cn.Close();
            }
            sw.Stop();
            MessageBox.Show(sw.Elapsed.ToString());
        }
    }
}

 上記のプログラムで計測すると、おおよそ ExecuteReader のほうが約2倍高速でした。ただ、この事実が知りたかっただけなんですが、結構大げさな記事になってしまいました。