はい、本日はC#でループで作ったりするなっがいSQLを作るときはStringBuilderクラスだぞって話し。
StrngBuilderクラスとは?普通のString型との違い
簡単に言うと通常のStringは+=でくっつけてく度メモリ上の領域を食っていきますが、
StringBuilderは一回生成すればそれでOKなので軽くて速いよって事です(雑)
加えて、あんまりそんな場面無いかもですが、もしも最終的な文字列長が予測可能なら、StringBuilder.Capacityプロパティで指定すると更にパフォーマンスが向上します。 先に確保する領域を指定してやる感じですね!
例えばこんな時に使う
大量のレコードが突っ込まれたデータテーブルを元にSQL文を作っていく場合。
Code_string
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
// 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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
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 とするとクリアが出来る。使う時ないけど。
コメント