Help us understand the problem. What is going on with this article?

SQL、サーバ、フロントで出来る処理は、どこにやらせるべきなのか

15743358488980752.png

ここで作成しました。
あ、ボクはやりたいことをやれたので満足です。フロントごめん

まえおき

SQLが最速なんだから、可能な限り処理はSQLにやらせるべきだよね!

というツイート(ネタかガチか分からない)を読んだ。この業界に銀の弾丸は存在しないはずだが……。

では、SQL、サーバサイド、フロントエンドで書ける処理はどこに書くべきなのだろうか?
それを判断する材料を考えてみた。

例題

DBの値 画面に出したい値
10 ¥10
999 ¥999
5000 ¥5,000
10500 ¥10,500
21000 ¥21,000

上記のDBの値をブラウザ上に表示させるという仕様があり、既に値自体は画面に表示できているが、三桁区切りと通貨記号(¥)を実装しなければらない!とする。

実装例

※一応書いたけど、そんなに重要じゃない

①SQL

下記はOracleの例だが、TO_CHAR関数を付けるだけで出来る。
サーバサイドのEntityをstring型に変更することになった。

-- Oracle (※DBに通貨記号の設定をする必要がある)
SELECT TO_CHAR(カラム名, 'FML999,999,999') FROM テーブル名;

②サーバサイド

下記はなんとなくC#だが、扱う金額によってはintで済まない。
処理はC#特有であるが、普通に先頭に通過記号つけて、三桁ごとに文字連結とかでもいいんだけどネ。

using System;
using System.Collections.Generic;
using System.Globalization;
public class Money{
    public static void Main(){

        // paiza.ioで試したんだが
        // デフォルトだとドルになっちまうんだナ
        CultureInfo jpn = new CultureInfo("ja-JP", false);

        // DBから取ってきたテイのList
        List<int> moneyList = new List<int>();
        moneyList.Add(10);
        moneyList.Add(999);
        moneyList.Add(5000);
        moneyList.Add(10500);
        moneyList.Add(21000);

        // 画面に表示させる値を入れるリスト
        List<string> moneyDisplay = new List<string>();

        // 3桁区切りで通貨記号をつける
        foreach(int money in moneyList)
        {
            moneyDisplay.Add(money.ToString("C", jpn));
        }

        // 出力
        foreach(string result in moneyDisplay)
        {
            // マジレスすると俺C#書けないわ。よくがんばった
            Console.WriteLine(result);
        }
    }
}

③フロントエンド

このAPIは対応していないブラウザもあるらしい
ブラウザ対応の都合を考えて、一般的には正規表現でやる。

const money = [10, 999, 5000, 10500, 21000];

// 便利なAPIで日本円にしてくれる
const formatter = new Intl.NumberFormat('ja-JP', {
    style: 'currency',
    currency: 'JPY'
});

const displayMoney = money.map(value => formatter.format(value))

// 配列を出力
console.log(displayMoney);

判断基準

①処理時間
この場合、レコードは5件しかないので、SQL、サーバサイド、フロントエンドのいずれでやっても人間にとっては些細な時間であろう。もしも千件、万件を画面に出そうとしているならSQLが圧倒的に早そう……だけど、少し思いとどまったほうがいいかもしれない。その仕様は本当に大丈夫?

②値の汎用性
もしも出力した値を計算に使う場合はDBでやってしまうと、サーバは文字列型として受け取ってしまうので、サーバ、フロント側で計算処理を書きづらくなる。したがって、SQL以外で処理した方が後で値を使いまわしやすい

③負荷
今回はほぼ影響ないが、処理をサーバ側でやるとサーバに負荷がかかるので、フロントのほうが良い。特に大量にアクセスされるページとかは、なるべくフロントにしたいところ。ブラウザ側で処理が遅くならないようにバランスは調整したい

④役割
この処理は「画面に表示させる処理」ではないので、サーバサイドで行う。「JavaScriptはサーバとの通信とDOM操作だけに徹底する!計算とかはしない!」ルールがあるなら、それもアリ。フロントとサーバの役割をぎっちり分ける会社、現場も一応見たことはある

⑤改修
あんまり気にすることはないかもしれないが、10年、20年後に改修するときにDBがOracleからPostgreSQLに変わるかもしれない。そうなったときに、SQLで関数を多用していたりすると書き直しになる可能性が高い。「SQL YYYY構文」(YYYYには年数が入る)以外の使用は可能な限り避けた方が良いだろう。
サーバサイドは言語のバージョンアップがあるかもしれない。言語の変更もあり得なくはない。フロントエンドはどうなんだろう(JSの改修案件とかみたことない)

※上記の判断基準は一例だが、SQLはオススメできない……。

image.png

まとめ

  • (基本的に)SQLの処理って早いと思うよ
  • 自分だったらこの処理をフロントエンドでやりそう
  • 銀の弾丸はない。現場のルールやいろいろな判断基準を元にどこで書くのが良いかしっかり検討しよう。最速だから何でもかんでもSQLにすればいい!ってもんじゃない

最後に

「いいね」ボタンを押して頂けると、うれしくなって記事を書けます。
あと、一緒に記事を書くIT芸人会の仲間を探しています。

Why do not you register as a user and use Qiita more conveniently?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away