はい、本日はC#でループで作ったりするなっがいSQLを作るときはStringBuilderクラスだぞって話し。
StrngBuilderクラスとは?普通のString型との違い
簡単に言うと通常のStringは+=でくっつけてく度メモリ上の領域を食っていきますが、
StringBuilderは一回生成すればそれでOKなので軽くて速いよって事です(雑)
加えて、あんまりそんな場面無いかもですが、もしも最終的な文字列長が予測可能なら、StringBuilder.Capacityプロパティで指定すると更にパフォーマンスが向上します。 先に確保する領域を指定してやる感じですね!
例えばこんな時に使う
大量のレコードが突っ込まれたデータテーブルを元にSQL文を作っていく場合。
Code_string
// INSERT文設定
string strSql = "INSERT INTO テーブルX \n";
strSql += "(ID, 名前, 性別,生年月日) \n ";
strSql += "VALUES \n ";
// レコード分ループ
for (int Cnt = 0; Cnt < Dt.Rows.Count; Cnt++)
{
strSql += "('" + Dt.Rows[Cnt]["ID"].ToString() + "',Dt.Rows[Cnt]["ID"].ToString(), Dt.Rows[Cnt]["ID"].ToString() + " ) \n");
// 最終行以外の場合
if (Cnt != Dt.Rows.Count - 1)
{
strSql += ",";
}
}
本番だと何万件置きとかに区切ると思いますが、こんな感じで作成してINSERTする事が結構あります。
でこれ普通のstringで行った形。
これだと冒頭でも書いた通りメモリの無駄遣いが激しく、結果的に処理速度の遅延に直結しています。
数千件とかならそこまで差は出ないですが、Dt.Rows.Countが数十万・数百万とかになってくると偉い違いが出ます。
なので、ループで長いSQLを作成する場合は下記のようにします。
Code_StringBuilder
System.Text.StringBuilder sbSql = new System.Text.StringBuilder();
// INSERT文設定
string strSql = "INSERT INTO テーブルX \n";
strSql += "(ID, 名前, 性別,生年月日) \n ";
strSql += "VALUES \n ";
for (int Cnt = 0; Cnt < Dt.Rows.Count; Cnt++)
{
sbSql.Append("('" + Dt.Rows[Cnt]["ID"].ToString() + "',Dt.Rows[Cnt]["ID"].ToString(), Dt.Rows[Cnt]["ID"].ToString() + " ) \n");
// 最終行以外の場合
if (Cnt != Dt.Rows.Count - 1)
{
sbSql.Append(",");
}
}
Appendが普通のstringでいうところの+=になります。これでどんどん追加を行っていく。
上にも書きましたけども、レコード数に比例して処理速度がダンチなので、
ループで文字列連結時はぜひ StringBuilderクラスを!
追加情報
Append以外にも、Insert(挿入)Remove(削除)Clear(削除)等一通りのメソッドがありますが、
少しだけ変わってるのがLength(長さ)。
普通のstringのLengthは長さを得る為だけのものだけども、StringBuilderのLengthは書き込みも出来てしまう。
例えばsb.Length = 0 とするとクリアが出来る。使う時ないけど。
コメント