株式会社ジーワンシステムの代表取締役。 新しいものを生み出して世の中をあっといわせたい。イノベーションってやつ起こせたらいいな。

スケーラビリティをあげるために、処理は極力DBサーバで行うべき

»

 予定を変更して。

 わたしの主張は単純ですが、結局、普通と真逆のことになります。一般に信じられていることとまったく逆のことを主張することは大変なことですね。

 わたしはブレてないのに、はぐらかすとか……。瑣末な部分にツッコミを入れるのが、はぐらかすことだと思います。「全部、否定する」って、これは現場でもよく言われるのですけれど(苦笑)、反対のことを主張しているのですから、最終的に否定にまわるのは仕方ないでしょう。否定しないことが議論ではないはずで、それを言ったら、地球は平らで太陽が回っていることに……。

 私は議論がしたいので、炎上上等です。

 一般的な考え方の反対のことを言ってますから、ドンドン否定してください。

 基本的な主張はこんな感じ。

 少し前に、議論になったのは、テーブル設計を後回しにするために、ロジックをストアドプロシージャで書きましょう、というわたしの主張に対して、「ストアドプロシージャにするとスケーラビリティが落ちる」という反論がありました。前に記事を書きましたが、それでも納得いただけないようですので、もう一度、APサーバで処理する場合と、DBサーバで処理する場合のそれぞれの処理量を考えてみましょう。

■ 条件について

 極端ですがJoinまでAPサーバで行っている場合と、DBサーバで処理した場合を検証しましょう。

 テーブルは

受注トラン
  受注NO(主キー)
  得意先ID
  受注日(インデックスあり)
  ・・・
得意先マスタ
  得意先ID(主キー)
  得意先名
  住所
  ・・・・

 処理内容は、1カ月の得意先毎の受注回数の一覧を出力する。

■ APサーバで処理する場合

・APサーバ

SELECT 得意先ID
FROM 受注トラン
WHERE 受注日 BETWEEN (1カ月分)
-- ORDER BY 得意先ID  普通はすると思うけど……。

のSQL文をDBサーバに送信する。

・DBサーバ

SQL文を受け取る。
SQL文のキャッシュを確認する。
キャッシュにあれば再利用し、なければ解析しアクセスパスを決める。
受注トランからインデックスを利用して抽出を行う。

結果セットを返す。

・APサーバ

取得した得意先IDをソートする
結果セットをループしながらカウントアップ
得意先IDがブレイクしたときに

SELECT 得意先名
FROM 得意先マスタ
WHERE 得意先ID = 結果セット.得意先ID

のSQL文をDBサーバに送信する。

・DBサーバ(得意先の数だけ実行)

SQL文を受け取る。
SQL文のキャッシュを確認する。
キャッシュにあれば再利用し、なければ解析しアクセスパスを決める。

得意先マスタからインデックスを利用して抽出を行う。
結果セットを返す。--増えてますけど、ここを赤くするかは微妙です。

・APサーバ

結果を出力する

■ DBサーバで処理する場合

・APサーバ

SELECT j.得意先ID, t.得意先名, COUNT(*) AS 受注回数
FROM 受注トラン j
  INNER JOIN 得意先マスタ t
   ON j.得意先ID = t.得意先ID
WHERE 受注日 BETWEEN (1カ月分)
GROUP BY j.得意先ID, t.得意先名
ORDER BY j.得意先ID

のSQL文をDBサーバに送信する。

・DBサーバ

SQL文を受け取る。
SQL文のキャッシュを確認する。
キャッシュにあれば再利用し、なければ解析しアクセスパスを決める。
受注トランからインデックスを利用して抽出を行う。
得意先マスタからインデックスを利用して抽出を行う。

メモリー上で得意先IDをソートする
結果セット用の変数(配列)に展開しながらカウントアップ

結果セットを返す。

・APサーバ

結果を出力する

■ APサーバで処理したらDBサーバの処理が減る?

 APサーバはどんなに処理が増えても簡単に増設できるので無視してOKです。DBサーバ側の処理のみに注目してください。

 DBサーバの処理が、青い部分はどちらで処理しても同等の部分、赤の部分が、APサーバで処理したら増える部分、緑の部分が減る部分です。

 APサーバで処理してスケーラビリティが上がるとしたら、

緑の部分赤の部分

が成り立つ必要があります。

 さらに、APサーバが無駄な処理をすることによって、APサーバの台数が増えても(設備費)、その運用コストの増加を考えても、APサーバで処理する方がよい、とお考えの技術者が大変多いわけです。

 つまり、

緑の部分赤の部分 + 設備費 + 運用コスト

が成り立つと、多くの技術者は考えているということになります。

 TCP/IPのようなCPUを大量消費するオーバーヘッドの大きなプロトコルでは通信していないのかもしれませんし、CPUの処理を肩代わりしてくれるNICも出てきていますけれど、当たり前ですが通信のコストはゼロではないです。ミドルウェアとのやり取りは、DBエンジン内部の処理に比べてオーバヘッドが大きいものになりますし、SQLの実行もオーバーヘッドが非常に大きいです。

 つまり、SQLの実行回数が増えるとDBサーバの処理は増えます。

 増える処理と減る処理が違う内容になって、実際には、データの重複の具合などの条件が個々に異なる。比較対象がそれぞれ違うので個別に考えないといけないでしょう。

 しかし、わたしはほぼすべてのシステムで不等号は反対になると考えますので、式を成り立たせるために左辺に何かを乗せないといけない。わたしには何が乗っているかは憶測するしかないですが、

緑の部分 + SQLの教育コスト + 下手糞がいる + SQLはイヤだ!
    > 赤の部分 + 設備費 + 運用コスト

となっているように思うのです。

 経営者としては、教育コストにフォーカスしてしまうのは否定しませんけどね。これらは技術者が言うべきことではないでしょう。

 わたしはそう思っていますけれど、もし、

緑の部分赤の部分

が成り立つとしたら、かなり多くのシステムで「SQLの教育コスト + 下手糞がいる + SQLはイヤだ!」などという本当の理由? を隠して、「スケーラビリティのために」という、単純かつ、とんでもない間違いボッタクってることになりはしませんか?(わざとやってたら耐震偽装を超える詐欺です)

 少なくともわたしは不等号が反対だと思っていますから、一度でも「スケーラビリティのために」と顧客に説明したことがあるなら、プロとしてのプライドを持って否定してください。

 炎上上等です。

■ 簡単な例だから?

 簡単な例でひっくり返らないなら、複雑な例でも同じです。

 しかし、複雑になれば違うことも確かに起こります。

 前に、Martin Fowler氏のブログについて書きましたが、例えば、Martin Fowler氏が例として書いたSQL

 SELECT o.orderID, o.date
    , sum(li.cost) as totalCost,
    CASE WHEN
      (SELECT SUM(li.cost)
        FROM lineitems li
        WHERE li.product = ’Talisker’
          AND o.orderID = li.orderID) > 5000
    THEN ’Y’
    ELSE ’N’
    END AS isCuillen
 FROM dbo.CUSTOMERS c
  INNER JOIN dbo.orders o ON c.customerID = o.customerID
  INNER JOIN lineItems li ON o.orderID = li.orderID
 WHERE (c.name = ?)
  AND (MONTH(o.date) = ?)
 GROUP by o.orderID, o.date
 ORDER BY totalCost desc

は、lineitemsテーブルの同じデータに2回アクセスしてしまいます。

 わたしが考えたSQLでは

 SELECT o.orderID, o.date, sum(li.cost) as totalCost,
    CASE WHEN
       SUM(CASE WHEN li.product = 'Talisker'
        THEN li.cost
        ELSE 0 END) > 5000
    THEN ’Y’
    ELSE ’N’
    END AS isCuillen
 FROM dbo.CUSTOMERS c
  INNER JOIN dbo.orders o ON c.customerID = o.customerID
  INNER JOIN lineItems li ON o.orderID = li.orderID
 WHERE (c.name = ?)
  AND (MONTH(o.date) = ?)
 GROUP by o.orderID, o.date
 ORDER BY totalCost desc

 lineitemsテーブルに対して1回のアクセス中に集計処理が入っています。実行計画を取れば分かりますが、Rubyで処理するのとほぼ同じアルゴリズムで処理されます。

 ところが、Martin Fowler氏のSQL文をDBサーバで行ったときの内部処理は、ブログのRubyで処理しているアルゴリズムより効率が悪いものになっています。

 つまり、SQLで書くことによって、他の言語を使っていたら起こり得ないミスをする人がいるということです。

 Martin Fowler氏のSQLは効率が悪いと言っても誤差の範囲(限られた範囲で二重にアクセスしているだけ)ですけれど、同じような間違いを繰り返すとDBサーバの負荷は高くなります。

 超高負荷になるシステムで繰り返し実行される処理なら、読みやすさ技術者のスキルと、トレードオフしてよいか考慮が必要になります。

 もちろん、電話帳を使うのに、電話帳を1ページ目から順にめくっていくようなSQLを書く人が居たら(珍しくない)、DBサーバは簡単にパンクすることになるでしょう。

■ まとめ

 ちゃんと作ればDBサーバで処理した方がスケーラビリティは上がります。

 しかし、現実的には、下手糞がいる(多い)ことを認める必要があるかもしれません。

 それを変えるのに必要なことは、教育コストと技術者の心がけだけです。特に、既得権を持っている上流技術者の意識を何とかしなければなりません。

 いろんな会社の新人教育を見ましたが、Java、C#、VB.NETなどはやっても、SQLはカリキュラムにすら入ってないことも多い。

 せめてJavaと同じぐらいの教育コストをかけてから、SQLでロジックを書こうというプロジェクトに出せば、若くてやわらかい頭なんだから、わたしぐらいはすぐに追い抜くはずです。

 SQLが高いレベルでできる技術者をそろえたら、工数が減って、パフォーマンスが上がって、運用コストまで落ちます。つまり、SQLを高いレベルで理解している技術者が増えれば、解決することは非常に多いのです(もちろん、十分条件ではなく必要条件です)。

 ここ(@IT)を見ている人、さらにコメントをくれる人などは、普通より確実にできる人でしょう。わたしのようなオヤジではなく、あなた方が業界を引っ張らないと行けないのですから、どうか自分の頭でよく考えてくださいね。

 神でもないわたしの言うことが全部正しいなんてありえませんから、是非是非、反論をください。いくらでも受けますよ。

 できればズバっと

緑の部分赤の部分

について反論して欲しいけれど、枝葉末節の部分でもがんばって受けます。

 炎上上等!(笑)

■ 追加です

 追加ですが、表示時のソートはAPサーバに任せることも多いです。その方が効率的なこともありますし、UIの要件と言えますから。集計時に内部的に発生するソートは任せようがないので、DBサーバの処理になります。

 しかし、本文の例なら、おそらくソートはDBサーバでソートすると思います。その理由はSQLの中でOreder Byの構文が単純だからです(決め付けはよくないけれどわたしが見た範囲ではそうでした)。もし、本文の例でDBサーバでソートまですると、四則演算しかDBサーバの処理を肩代わりしていない。

 パフォーマンスが落ちても、工数がかかっても、APサーバのコスト(設備・ランニング)が増えても、確保したいスケーラビリティのはずなんですから、スケーラビリティだけは、際限なく上がるぐらいでないと意味がないのですが、わたしの考え方が正しければ、ソートまでDBサーバでやったら、確実にスケーラビリティは落ちます。

 APサーバで処理しているのだから、DBサーバの負荷はなんとなく落ちそうな気になるでしょうが、プロがやる仕事なんですから、なんとなくではなくもっと論理的に考えて欲しいものだと思うのです。

Comment(38)

コメント

誰かは知りませんが、コメントどうも。

つまり、パフォーマンスが落ちようと、工数が掛かろうと、運用コストが増えようと、「スケーラビリティが上がる」という顧客には分かりにくい理屈を言って自らのスキルの低さを補うのですね。

分かります。いっぱい居ますから。
技術者なら、理屈で勝負すべきですが、それが出来ない自称技術者もたくさん見てきました。
どうぞ、カスは、カスの技術者として生きてください。

私は微力ながら、あなたの様なカスを全力で駆逐しようとがんばります!!
エネルギーを頂いてありがとうございます。

技術は多数決じゃないですよ。
スキルがない技術者の割合を見て、教育コストを考えて、最終的に方針を決めるのは経営者のすることです。

一介の技術者は技術を追うべきです。

MR.CBR

> いろんな会社の新人教育を見ましたが、Java、C#、VB.NETなどはやっても、SQLはカリキュラムにすら入ってないことも多い。
→私は製造業で社内SEをやっていますが、私の会社(情報部門)での新人教育の
 最初はSQL教育から始まります。(ビジネスマーナとかも当然行いますが)

 現場に近い所にいると、圧倒的にSQLに触れる機会が多いのです。
 現場の依頼や要望がそのままSQLになっている事も多々あります。

MR.CBR さん、ども。

IT業界の末席に名を連ねるものとして、本当に恥ずかしく辛い現実です。
IT業界では、とりあえずJavaを教えて現場に放り出すのが普通で、以前は、JOIN禁止とか、GROUP BY禁止とかありましたし、今でも普通にHAVING禁止はありますよ、いわゆるIT企業で。
つまり、顧客(ユーザ)の方が分かっていて、進んでいるということで、本当に、そういう話を聞くと悔しさで身悶えてしまいます。

それで、私は同業者に対して、「プロとしてのプライドはどこにあるのか!!」という思いで、口汚くなってしまいます。

プロ(技術者)ではなく、サラリーマンなら上に従うわけです。

これぐらい不況になっても、それなりに報酬を得れて、それだけがアイデンティティの自称技術者達は、結局、技術者ではなくサラリーマンですから、自分の頭で考えることはありません。
空気が大事ですしね。

それは生き方として、間違っているとはいいがたいけれど、今みたいに不況になったら本物以外は生き残れないと思います。

私としては、くだらないサラリーマンを淘汰するチャンスとして不況は歓迎なのですけれど、私自身が不況に耐えれなさそうで、痛し痒しです(笑)

MR.CBR

>IT業界では、とりあえずJavaを教えて現場に放り出すのが普通で、以前は、JOIN禁止とか、GROUP BY禁止とかありましたし、今でも普通にHAVING禁止はありますよ、いわゆるIT企業で。
→絶句…。
 JOIN、GROUP BY、HAVINGが禁止という事は当然、副問い合わせも禁止
 なんですよね…。SELECT文でデータ取ってきてプログラムでグルグル回す
 しかないですね。つ、辛すぎます。
 このルールだと、現場からの要望の大半であるSQLだけで済む事を
 わざわざグルグルプログラムを組むしかないですね…。

 弊社でそんなプログラム組んだら大目玉になります(笑)。
 というか、プログラム中にループがあると、そのループは本当に
 必要なのか?(SQL一発で出来ないのか?)というディスカッションに
 発展します。弊社では卓越したSQLアーティスト(笑)はいないですが、
 3人ぐらいで考えると、ループせずにSQL一発で出来るケースが多いです。
 その甲斐あって各人のSQLのレベルは年々向上しているし、SQLを使うから
 保守性が落ちるか?というと、プログラム中にループが沢山登場する
 よりかよっぽど保守性が高くなります。(弊社の場合ですが)

 ただ、悩みは弊社の場合、動的SQLが多く、各プログラム・テーブルの
 CRUDが俯瞰できていないと言う点です。
 業務変更により、テーブルに項目追加が発生した場合の影響分析を
 現在はVBソース、PL/SQLソース、SQLスクリプトソースからGREP
 かけて対象PGを洗い出しています。この辺をもっとスマートにする
 事が課題です。何か良いアドバイスを頂ければ幸いです。

saki1208

いつも楽しく拝見させていただいています。
# 共感できるところが多いんですよね。
# この業界、なぜか苦労したがるひとが多い気がする。

私の周りにもたくさんのなんちゃってSE/PGが大量にいます。
二言めには、「だって、俺できないもん」ですから...
# やらなければいつまでたってもできないんですがね。

>IT業界では、とりあえずJavaを教えて現場に放り出すのが普通で、以前
>は、JOIN禁止とか、GROUP BY禁止とかありましたし、今でも普通にH
>AVING禁止はありますよ、いわゆるIT企業で。
うちでは一時期「UNION」禁止でした。
もちろん、副問い合わせもでしたが。

余計な話ですが、CNETの方はやめられたんですか?

saki1208

日本語が変でした。

×たくさんのなんちゃってSE/PGが大量にいます。
○たくさんのなんちゃってSE/PGがいます。

ビガー

ビガーです。

赤と緑の部分への突っ込みが欲しいようなので。

そもそもの話ですが、得意先マスタのようなマスタデータ(更新頻度や
運用要件に依る)は高速性が求められるシステムではAPサーバ内に
キャッシュします。(マスタメンテ時にリフレッシュさせたりする)

したがって、例がよろしくないと思うので受注と出荷などを例にするとよいかと。
その場合について意見しておくと、O/Rマッパの機能でもある程度イけますが、
クエリ言語の仕様にイライラすることが結構あるのでApplicationFramework
(例えばspringベースにしたもの)内でHibernateTemplateとJdbcTemplateを
それぞれ使用できるようにして永続化・簡易検索はHibernateTemplate、
重めの検索はJdbcTemplateを使用してエンティティにマッピングさせたりします。
JdbcTemplateを使用する前提としてSQLを熟知している必要がありますね。

MR.CBRさんの話ですが、失礼ですがこういうのをスパゲッティと一般にはいうのかと。。
解決策は以下のようなアプローチになりますかね。
1. 業務と対応するプログラムを表形式などで洗い出す
2. プログラムとテーブルの対応を表形式などで洗い出す。
3. CRUD表にまとめる。

1.と2.は非常に地道な作業です。たぶん業務中に工数を与えられてやるような
仕事ではないでしょうから、保守案件受注時などに並行して地道にやるしかないでしょうね。

その後のCRUD表メンテナンスが面倒と思いますが、地図が現実と剥離しては
意味が薄れると同様に組織的に重要なことであると認識する必要があります。
→これが一番大変なんですけどね。。

MR.CBR さん、ども。

御社のシステムを作れるITベンダーは少なくとも上場企業にはないですね。
冗談抜きで、ITベンダーなどが作り直したら100倍遅いものができてくると思います。

動的SQLを使っているとCRUD表は確かに難しいですね。
PL/SQLで静的なものにしておくと、ある程度はSI Object Browserなどで作ってくれますけれど。
あとは1度手作業でしっかりしたものを作って、変更の都度、修正するということになろうかと思います。

saki1208 さん、ども。

> 二言めには、「だって、俺できないもん」ですから...

これを言われた後、ループして作ってパフォーマンスが出ずに結局作り直しとかありますね。

最近は、ハードがよくなっているから、パフォーマンスの問題が出るときは本当にデータ量が多くなったときで、逆に深刻な問題になることが多いですね。

CNetはさっき少し書きましたけれど、使い勝手が悪くて、なんとなく書きたくないのです(笑)

資金繰り

APサーバとかDBサーバとかどうでもいい。
とにかくこのシステムを今すぐ動くようにしてくれ。
4月の本番稼動に間に合わないなら、損害賠償を請求する。

と言われ・・・

結局、一部の機能が正常に動かなくて、使い物にならず全てパーに 
→ 損害賠償請求(XXX億)
→ 幹部社員が転職しだす
→ 社長が金策に走る
→ その筋の方が会社に怒鳴り込みに来る
→ 会社に泥棒が入る(社長の自作自演?)
→ 社長が行方不明に
→ 会社倒産

これ去年の出来事。

とにかくシステムが動けば神。

SQLだろうがRubyだろうが、動けば神。

APサーバだろうがDBサーバだろうが、動けば神。

ビガーさん、ども。

> そもそもの話ですが、得意先マスタのようなマスタデータ(更新頻度や
> 運用要件に依る)は高速性が求められるシステムではAPサーバ内に
> キャッシュします。(マスタメンテ時にリフレッシュさせたりする)

確かにキャッシュさせればDBサーバの処理は肩代わりできますね。
考えが固定されていました。
ありがとうございました。


> クエリ言語の仕様にイライラすることが結構あるのでApplicationFramework
> (例えばspringベースにしたもの)内でHibernateTemplateとJdbcTemplateを
> それぞれ使用できるようにして永続化・簡易検索はHibernateTemplate、
> 重めの検索はJdbcTemplateを使用してエンティティにマッピングさせたりします。
> JdbcTemplateを使用する前提としてSQLを熟知している必要がありますね。

重めの検索とか、難しい検索とか、基準を個人にゆだねると人によって変わる。
何をもって簡易検索というかということです。
できない人はいつまで経っても簡易でループに流れますから、UIとSQLを書く技術者を完全に分離した方がいい(もちろん、できる人は両方してもいいけれど)

そのためには、DBサーバで処理させる必要が出てきます。
できる人が作るならばスケーラビリティは関係ないのです。

資金繰り さん
おはようございます。

大変なことがあったのでしょうね。
何億というプロジェクトでは、個人の力ではどうしようもないでしょうから、早く忘れて技術を磨いてください。

とおりスカリー

私はPostgreSQLを主に使っていますが、ストアドにビジネスロジックを
作りこむには、ソースが長くなってくると言語仕様が少々貧弱で
いまひとつ踏み切れません。
全ての関数がグローバルだったり、グローバルな定数が無い等・・。

また、ロジックを100%ストアドに収めきれる訳でもなく、
ストアド/Java両方に注意を払いながらメンテしていくのも
ちょっと抵抗が。


ところで、HibernateのようなORマッパーって、「これでSQLが要らなくなる」という
誤解がくっついて広まってるのが不幸ですね。

とおりスカリーさん
おはようございます。

PostgreSQLのストアドですか、割りと使えますけれどね。
SQLにシンタックスエラーがあっても通ってしまう?つまり、全部、動的SQLとして認識しているとか、すべての関数がグローバルというのは、確かに嫌なところです。

ビジネスロジックのすべてはムリですが、内部、外部(UI)に分ければ、内部はすべてストアドプロシージャで処理できるはずです。
そこにデータがあるのですから。

インドリ

> ただ、悩みは弊社の場合、動的SQLが多く、各プログラム・テーブルの
 CRUDが俯瞰できていないと言う点です

この件ですが、そのためにストアドプロシージャが存在します。
ストアドプロシージャを作って、トランザクションの正規化をしましょう。
正規化は何もテーブルだけではありません。
プログラムやトランザクションも正規化する必要があります。

インドリ

>ストアドにビジネスロジックを作りこむには

この件ですが、PostgreSQLはORDBMSなので、データ中心アプローチで考えてストアドプロシージャを作らなければなりません。
ですから、ストアドプロシージャにするのは、「データ要件」のあるものだけです。
データの整合性という点に注目すれば、自然と上手く作れると思います。
Javaと同じ感覚でストアドプロシージャを作っちゃ駄目ですよ。

インドリさん

>> ただ、悩みは弊社の場合、動的SQLが多く、各プログラム・テーブルの
>> CRUDが俯瞰できていないと言う点です

> この件ですが、そのためにストアドプロシージャが存在します。
> ストアドプロシージャを作って、トランザクションの正規化をしましょう。

依存関係までしかわからないから、CRUDにはならないですよね?
CRUDになるツールを作ろうかと何度も思ったのですけれど、すべてがストアドプロシージャになるプロジェクトって世の中にあまりないでしょうから、売れないしな~って、何度も諦めています。

ストアドプロシージャ(SQL)が難しいという前提があるから、最後の手段としてストアドプロシージャになるのでしょうけれど、実は簡単となれば、最初から全部ストアドプロシージャが正しい選択になるはず。

MR.CBR さんの会社のシステムはVBを使っているとのことですから、10年近い蓄積があるのでしょう。
ストアドプロシージャでやり直せたらよいけれど、そうそう予算も取れないでしょうし、情報システム部で業務が回っているなら十分じゃないでしょうか。

リプレースするときは、是非やらせて欲しいですけれど(笑)
10年前ならOracle8iとかで、8iの頃はEnterprise版でないとOLAP関数が使えなかったと記憶しているのですが、Oracle9i以上ならOLAP関数は結構使えるので、CASE式と組合せばSQLでかなりのことが出来ると思います。

MR.CBR

インドリさんはじめまして。

>この件ですが、そのためにストアドプロシージャが存在します。
>ストアドプロシージャを作って、トランザクションの正規化をしましょう。
→この件、凄く興味があります。問題解決の糸口をつかめれば嬉しい限りです。
 トランザクションの正規化とは具体的にどのような作業になりますか?
 弊社ではストアドプロシージャにて基本は静的SQLなのですが、
 検索条件多く可変な場合や、どうしても性能を出さないといけない時など
 ストアドプロシージャの中で動的SQLを組みます。
 
 生島さんが言われる通り、弊社もObjectBrowserは無くてはならないツールで
 利用していますが、相関図機能を使用して静的SQLの相関は判りますが、
 CRUDのどれか?と動的SQL(当たり前ですが)は対象外なのです。

 ビガーさんが言われる通り、1、2の作業をまめにやっていくしかないのでしょうね。

 弊社のシステムはテーブルが446本、プログラム(VB、PL/SQL、SQLスクリプト、
 Bat、VBスクリプトなど)が800本近くあり、CRUDマトリックスがExcel2003では
 実現できません(笑)。※列最大が256列な為

ビガー

ビガーです。

MR.CBRさん

1枚のシートでは管理できないでしょうから以下のような観点で
シート分けするなどは必要でしょう。
1. 業務とプログラムの粒度を合わせる。
2. 1.レベルのメインプログラムとサブプログラムの対応をとる。
3. プログラム区分(実装言語やSQLの質(動的/静的)で分割する。
4. テーブル区分(マスタ/トラン/システムなど)で分割する。

これらを実施すると本当に必要な機能やデータがわかり、最も効率良い
機能拡張ができるようになります、私の場合は。
どこまで本気かが重要ですね。

インドリ

挨拶が遅れました。MR.CBRさんはじめまして。
DBMSを使用したプロジェクトのよくある間違いが「業務イベント」用いる事です。
例えば、商品を発送した、死に筋商品を廃棄した・・・とかの業務処理がこれにあたります。
これが何故間違いなのかと申しますと、こうした視点で作られたプログラムは、ロジックが分散するからです。
そうなってしまっては、何のためにDBMSを使っているのか分からなくなります。
そこで、企業単位で業務手順や用語の統一化を図り、業務処理=トランザクションを細分化し、これを正規化することによりプログラムの重複がなくせます。
コツは安定したデータに着目する事です。
業務手順は時間と共に変りますが、業務に根ざしたデータそのものは企業活動が変らない限り(業種変えなどしないかぎり)変りません。
そのデータを判別し、そのデータの操作をストアドプロシージャ化し、業務手順は別に定義する事により変化に強いシステムが出来上がります。

インドリ

念のために付け加えます。データの操作というのは、データライフサイクルの事です。
CRUDが把握できない時はトランザクションが正規化されていない可能性大です。

おそらくですけど、MR.CBRさん自身はCRUDは把握できていると思います。
できてない人は、SQLでやった方が保守性が上がるとは言わないから。

ただ、他の誰かに説明するのにCRUDが必要で、それの保守に困ってらっしゃるのでしょう。

これを解決するには動的SQLが減らないと、ツールではどうしようもないですね。
446テーブルというにワークが含まれているとしたら、それをまずはじくことでしょうね。
私はワークテーブルは、スキーマを変えたり……。

ウソ、基本ワークテーブルは使わない。
ただ、横着者なので
Create Table xxxxx AS
SELECT * FROM YYYYY

とバックアップしたヤツがたくさん残っていることがある。
本番前には消しますが。

インドリ

おっと失礼。重要な事書き忘れていましたが、トランザクション正規化した後は、絶対にCRUD表は必要ですよ。
此れ書いておかないとデータベース設計としてはミスです。

通りスガリン

はじめまして。
カスって呼ばれる覚悟で書きますね。
私は、上記のように条件が静的な例ではCASEでも
なんでもつかってとにかく早いSQLをがんばって作って
DBサーバー内で演算処理することにしてます。
従って、APサーバーに演算処理をゆだねることはありません。
生島さんの意見に激しく同意!なのです。

ですが、UI用件によっては、APサーバーに演算処理を
シコシコ書く場合があります。
抽出結果に対して動的に再計算をさせたい場合です。
一度抽出された結果を例えば選択された行だけの合計結果を得たい
とかそういう時は、APサーバーのキャッシュ内のデータを
使って演算処理するようあらかじめ設計します。
このような再計算処理は、DBに再クエリを投げない(必要もない)ので
何回実行してもDBサーバーの負荷がかかりません。
また、再CGI処理せずにjavascript等で再計算できるのも利点です。

一画面で複雑なシミュレーションしたい場合とかは、
DBサーバーで必要なDB情報を抽出して、APサーバーで
配列化および演算設計(javascript)をしたりといったことは
よく行ってます。

DBデータの排他条件等が限られた場合のみ有効な手段ですが
DBサーバーもAPサーバーもクライアントのキャッシュも(笑)
限られた資源を有効活用して設計するという考えは何を差し
おいても正しいことだと思いますし、
そこに知恵を出すこと=エコ思想があるということでは
ないでしょうかね。

貧弱サーバーでやってるうちは自分の設計下手が身に
しみてわかるのですが、最近のサーバーは高性能すぎて
設計下手でも貧弱サーバ時代よりより処理時間が
早かったりするから気づきにくいかもしれませんね(笑)

長文でお邪魔しました。
論点がずれていましたらお詫びいたします。

通りスガリンさん
おはようございます。

ちゃんと自分の頭で考えて、特定の処理をAPサーバに任すというのは正しいと思います。

例えば、前にコメント欄で議論したのですけれど、(これはWebではなくリッチクライアントでやった方が…)生産管理でライン変更などのシミュレーションをするのは、バッチで粗いデータをつくって、それをメモリー上(クライアント・APサーバ)でユーザが何度もシミュレーションすることになりますが、このとき途中の情報をいちいちDBに戻したりはしないでしょう。

つまり、シミュレーションは【外部要件】と私は考えています。
【外部要件】はクライアント・APサーバで、【内部要件】はDBサーバという考え方なのです。

本文は、そういうレベルの高い話ではなく、それ以前の問題で、何も考えずに、「スケーラビリティのためにAPサーバで処理します」という人を駆逐したいだけです。

弊社が最初から入れたらよいのですが、「APサーバで処理します」と上流で言われて、機器やハウジングの見積などしちゃったら、もう、ひっくり返せなくなりますからね。上流がSQL(DB)を分かっていなかったら「DBサーバで処理します」という選択肢は、最初からないわけです。

ビガー

ビガーです。

ごちゃごちゃと理想論を発言してきましたが、資金繰りさんの発言は
この業界をよく表していて、私が経験してきた仕事の半分くらいを
占めている気がします。

そういう状況では多くのメンバの思考が停止してしまっているので落とし所
への道筋を作ることが重要ですね。
優先度の選定とコンセンサスの再形成。つまりは利害関係者の納得所を
探すことになりますね。
下流の仕事ももちろん重要ですが、下流の仕事にも限界(範囲)があるので
上流の技術力を高めることをお勧めします。
取っ掛りとしては、清水さんのプロの学び力という本は大いなる学びになります。
(単純にすばらしいと思ったので紹介しました)

Oumi

実際、面白く読ませてもらっていますが、それだけでは申し訳ないなと思い、こういう考えの人もいます的な程度で投稿させてもらいます。

「いや、だから緑だってば!」(ぇ

ストアドプロシジャを使用した場合、業務を実現するコードの配置先は、
APサーバ(等):DBサーバ(ストアド)⇒データストア(DB)
となります。
ストアドプロシジャを使用しない場合、業務を実現するコードの配置先は、
APサーバ(等)⇒データストア(DB)
このメリットは、リカバリ運用、資産管理の面で、単純化し易いということです。
後者の場合では、DBに対する無駄なネットワークトラフィックが問題になってくるのも確かです。
(まだまだ、観点はいろいろあるとは思いますが・・・)

よって私はこう思います。
開発人数が多い場合、当然システム開発リソースも多い場合ですが、これは、開発運用やDB運用の単純化をできるだけ行う必要があるため、中心となる(ダウンタイム0である必要のある)DBは、ストアドプロシジャなどは配置しない前提で進めます。
(問題の起きる可能性を0に近づけたいですから)ただし、性能見地などから特権的に配置する場合はあるでしょう。
ちなみに、常に1000名以上の開発者が常時動いているようなプロジェクトでは、色々と怖くてストアドを使いましょうなんてなかなか言えません(でした)。
高度にSQL文を知っているという事より、それ意外で多くのスキルや運用解決が必要となる事柄が多いと感じます。
例えば、問題特定の一般化を行う方法が複雑になる可能性、また例えば、性能確保のために検討すべきこと、リカバリ時のデータと資産の分離方法、その細かなコントロールの仕組み。エンドユーザの教育。多々あると思います。


逆に、システムのアーキテクト(的な立場の人)が、システム全体を網羅的に見ることができて、かつシステム開発リソースを把握できるような規模の場合、ストアドプロシジャは有効に利用すべきでしょう。当然リカバリーや、スケールアウト時の方法論も含めて検討されなければなりませんが。

ですので、SQLそのものが云々より、性能・リカバリーへのインパクト、スケールアウト時の影響度合いや、システム開発の状況などから、考えるべきと思っています。つまり、どの程度まで誰に(どの部分に)ストアドプロシジャの利用を開放するかということです。


こちらの読み手の方々は、それぞれの方が様々な立場で活動していらっしゃるでしょうから、同じ言葉でも受け取るシーンが異なっているために、そもそも意図していることが伝わらないのでは?なんて思っています。
(上流の定義がそれぞれの人で異なるように)

スケーラビリティという言葉で、
性能、資産運用、問題の特定化、対処方法、システム運用、設計、etc...
などを網羅的に言っているのだと信じたいっ!(うーん


議論のモデルが、要求に対しすぐさまSQLに脳内変換し、すぐにリリースできる規模(またはそれを要求される)のシステムということであれば、おっしゃっている事には全て同意できます。

なんていうか、ただ炎上するだけっていうのは、面白みに欠ける気がします。
もう少し、前に進む感じがほしぃなぁ・・・


追記:私はストアドいらない派です、なぜなら
ストアドが早いDBより、使いやすくちょっ速(ぱ)やなオブジェクトDBが登場してほしい!からです(^^;

読み返してみると、結構まとまってないなぁ・・と思いましたが、「ポチッ」

Oumi さん
こんにちは。

おっしゃってる内容は、下手糞がクチャクチャにするのが怖い。ということになろうかと思います。
私も怖いです(笑)

> 性能、資産運用、問題の特定化、対処方法、システム運用、設計、etc...

つまり、性能、以外はできない人の言い訳か、できない人が多いという問題に帰結するだけじゃないですかね?
できる人にとっては、大きかろうが小さかろうが一緒です。

現実的な問題は、大きくなればなるほど、できる人間が揃わないということだけです。
それは技術者の怠慢だと煽っているわけです(笑)

大きなシステムでは失敗するのを指をくわえて待って、どうしようもない部分(サブシステム)を丸ごとやり直すぐらいですね。

経営者なら、教育コストと天秤に掛けて、DBは選ばないこともありえますけれど、技術者が言うことじゃないと……。

世の中で、Javaに費やされた教育時間と同じ時間を掛けて教育したらできるでしょうが、講師役が既にショボかったりしますから難しいです。

インドリ

規模の大きいシステム程ストアドプロシージャが必要だと思うけど・・・
だって、ストアドプロシージャは、多言語で作られた大規模システムに於いて、ロジックを集中管理できるのでかなり有効ですからね。
大規模システムだからこそロジックが分散するのが怖いと私は思います。

常時1000名以上の開発者がいるシステムは経験ないけど、平均して顧客が払う人月単価(末端価格)を100万としたら月額10億ですからね。
1000名がたった1年で解散するようなことはないから、ハードのけて数百億のプロジェクトですね。

もちろん、それだけの巨大プロジェクトならストアドプロシージャにロジックを入れて、参照系はJava、アドホックにRuby、入力系はリッチクライアントの.NetとUI側の特性を活かした方が圧倒的に効率が良いです。
そういう記事も後で書こうかと思っているのですけれど。

> リカバリ運用、資産管理の面で、単純化し易いということです。

ストアドプロシージャのバックアップ、世代管理なんてのはできない方がおかしいし、データとロジックが一緒になっていても何が問題なのか分かりません。それだけの巨大プロジェクトで、おいそれとOracleがSQLServerに変わったりすることはありえないですから、目一杯ベンダー依存の機能を使っても大丈夫です。

しかし、それだけの規模でSQLを高いレベルで理解している人を(例えば300人)集めるのは(育てる気がなければ)至難の業、というか不可能?じゃないかと思います。

ですから、私も過激な人間ですが1000名規模で「すべき」とは現状では言えない(笑)

経営者が本気で教育する気を持てば、それだけの技術者が生まれ変わって、その後、散らばってくれるので業界が変わって面白いことになる。

権威(Iで実績とかNで実績とか)に弱いからね、自分で考えれない人たちは。

tano

Oracle8iが出た当時、3階層モデルをオラクル自身が一生懸命宣伝していました。
当時、私はUIと外部通信以外は全てストアドの業務パッケージを作ったので、
非常に戸惑いました。

何しろOracle通信とか読んでも、直接的な悪口こそないものの「PL/SQLはデバッグが難しいため、複雑なことは出来ませんが、バッチ処理等には非常に役にたちます」とかUIのバックエンドでストアド使うのは、なんとなくダサいという印象を与える記事があって悲しかったこと覚えています。被害妄想かもしれませんが。
生島さんの記事を見て10年間状況が変わっていないのだなあと感じました。
単なる感想ですみません。

tano さん
おはようございます。

PL/SQLはデバッグはしにくいと言えばしにくいです。
ループしなければ一緒ですけどね。

デバッグしにくいと言う人は、ループでものを考えていると思います。

例えば、弊社で中小企業に基幹システムを丸ごとストアドプロシージャで作っても、ストアドプロシージャ内でループしているのはほんの数ヶ所所です。(パイプライン処理を使うので全部ともいえますが)

OracleはストアドプロシージャでSELECT系の処理をやりにくいと言う大きな欠点がありますので……。

SQLServerがお勧めです。
Webになって、非接続になったのですから、Row Lockとか、ダーティーリードとか関係ない(自前で解決しないといけない)ですから。

インドリ

「下手糞がいる」というところで連想したのですが、このまま教育をせずに下手糞を避ける上流の人達の理屈で行くと、「プログラミングは下手糞が居るから・・・」となって全て偽装、もしくは他国から調達という事になってしまうという気がします。
プロなのに教育を避け学生レベルの知識に頼る非常におかしな業界ですね・・・
この業界の先行きが非常に心配です。
現に最近の流行は「保守性」で逃げる事らしいです。

言い訳の例:
テンプレートは「新人が分からないから保守性が低い」
多重継承は・・・
C++は・・・
アセンブラは・・・
三項演算子は・・・

そのうちオブジェクト指向は保守性が低い(笑)となる事でしょうね。

保守性とスケーラビリティは二大いいわけですね。
私は保守性は先に「出来ない言い訳」と潰してたから、スケーラビリティが出てきたわけです。

実際には、ケースバイケースで判断できれば良いわけですけれど、判断できるレベルまで知識が追いついてないでしょう。
ってことなのですけどね。

現実論として、規模が大きくなれば人が揃いません。

今は仕方がないからサブシステムだけでもとか、教育期間を準備するとか、そういう風に考えてくれる人が出ないかと思っています。

下手糞のやり方を指定して海外に出して人海戦術で終わらすぐらいなら、国内で技術を磨いて爆発的な生産性で勝つ方法もあるだろう?
って、私が儲かってたら言えるんですけどね(笑)

空洞化したら、回りまわって、自分の首を絞めるというのに。

もっと問題は、オブジェクト指向などに比べても上流のミスが尾を引きます。
つまり、普通の実装と違って、かなり上流まで判ってないと蓋を開けたらエライことになってしまいます。

だから、外部、内部と分けた方がよいのですけれど、そうすると今まで上流だった人はSQLを憶えなければ相当立場が下がってしまうわけです。
既得権を失いたくない人たちがそれを認めるわけはないです。
結果、業界が腐っていきます。

何年も前から変わらない結論ですけれど。
オフショアのお陰で、加速的に酷くなっているような気が…。

komatsu

・DBのサーバー追加の方がコストもかかりダウンも伴います。
・レベルの低い技術者でも成功させるプロジェクトがいいマネージャーでいい設計かと思います。
・上の例で「得意先マスタ」がIOの負荷の原因で違うサーバーに移行したいときJOINしてた場合どうしますか?
・ストアドとか使うとヴァージョン管理できない気がしますがどうしますか?
デメリットも多いと思います。

コメントを投稿する