課員の売上予定と実績のテーブルは、
create table #縦持ち
(
社員CODE char(10) ,
月 integer ,
予実 char , -- 'Y'予定 'J':実績
額 integer ,
)
このように、縦持ちにします。
しかし、
"create table #横持ち
(
社員CODE char(10) ,
予定額1月 integer,
実績額1月 integer,
;;;;;;;;;;;;;;;;;;;
予定額12月 integer,
実績額12月 integer
)
のように、横持ちするプロジェクトを往々に見かけます。
RDBの項目設計で、同類項目を横に持つと、「なんだかなぁ」といってしまいます。
そのとき
「正規化して、縦持ちするとIO回数が増えてパフォーマンスが落ちるので、横持ちしている。」
という言い分を聞きます。
200人の課員を想定します。
縦持ちだと, 200人* 予実2行 * 各月12行 => 4800行
横持ちだと、 200人 200行
その差は,24倍
データ作成は、物理的なIOを伴うので、縦持ちと横持ちの差は、20倍以上要し
縦持ちだと、横持ち表に展開するのに、加工時間がかかり、そのコストは大きい...と横持ち論者は仰る。
口論しても前進しないので、どれ位の差があるか、確認してみました。
http://ognogn.com/Bekkan%2fMsSQL%2f%e9%80%9f%e5%ba%a6%e6%af%94%e8%bc%83%2f%e7%b8%a6%e6%8c%81%e3%81%a1%e3%81%a8%e6%a8%aa%e6%8c%81%e3%81%a1.aspx
(縦持ち 4800行と横持ち200行の各月のデータは 乱数取得していて一致しません。)
(縦持ちデータを横に取り直した表は、一致してます。)
縦横変換は、一般的な
select 社員CODE
,SUM(CASE WHEN 月 = 01 and 予実='Y' THEN 額 else null END) 予定額1月
...............
,SUM(CASE WHEN 月 = 12 and 予実='J' THEN 額 else null END) 実績額12月
from #縦持ち group by 社員CODE order by 社員CODE
で行いました。
実行例:
作成所要時間 (縦持ち)00:00:01.7187500 (横持ち)00:00:00.2031250: 横取得: 00:00:00 (縦横変換)00:00:00.0781250
縦持作成は 1.7秒 横持ちは 0.2秒で 10倍以下。(挿入時間なので、この差がネックに場面は少ないと思ってます。)
縦横変換で縦持ちデータを横持ちに変換するのは 0.07秒
(試行した私が差の小さいのに感心しているのは秘密です。)
「だから、縦持ちがよい」と結論つけるのは乱暴ですが、少なくとも、縦持ちは速度的に不利ではないと言えそうです。
想像ですが、縦横変換のSQLを項目毎に (select 月where),(select 月 where)....と副SQLで記述していて、縦横変換は遅いと、なったのかもしれません。
P.S. 当該ページにバグがあります。
Postback処理がすべて無効になりアベンドします。(既知の不具合ということで、ゴニョゴニョ...orz)