DataTables で表示速度が遅くてお困りの方へ


こんにちは、Webシステム部の長谷です。
皆さんDataTablesというものをご存じでしょうか?

Webプログラマーの方なら結構知っているかと思いますが、簡単に説明をすると、HTMLテーブルのページング・ソート・検索機能を簡単に実装ができる便利なjQueryのプラグインです。

こちらビヨンドのプロジェクトでもよく使用しています。

PHP側でページング・ソート・検索機能の実装をしなくて済むので楽ですし、操作性もかなり優れているのですごく重宝しているのですが、ただひとつデメリットがございます。

表示速度が遅い

まあ当たり前の話なのですが、データの件数が多ければ多くなるほど表示が遅くなってしまいます。

どれくらい遅いかっていうと、PCスペックに依存はするのですが、10000件のデータを表示するのに30秒近くかかってしまうくらいには遅いです...

データを取得すること自体にはさほど時間は掛からないのですが、データを取得してからjQueryでのテーブルの描画の処理に時間が掛かってしまっているのが主な原因の様です。

表示を速くする方法

ただ、このテーブル描画の処理を速くする方法がございますので、今回はその方法をご紹介します。

JSON形式で直接jQueryにデータを渡す

ビュー側でtable, tr, tdでデータをすべて出力してから、DataTablesで描画の処理をするよりも、ビュー側ではtableだけ出力して、データはJSON形式にしてDataTablesに直接渡して描画の処理をした方が、表示処理速度が速くなります。

では、実際にコードを見てみましょう。
今回はFuelPHPを使用しておりますが、ほかのフレームワークでも同様のやり方で対応可能です。

変更前

■ Controller

$users = Model_User::find('all');

$this->template->content = View::forge('users', $users);

■ View


<div class="user-list">
    <table class="datatable table table-bordered table-sorted text-center">
        <thead>
            <tr>
                <th>Id</th>
                <th>名前</th>
                <th>年齢</th>
                <th>身長</th>
      	        <th>体重</th>
            </tr>
        </thead>        
        <tbody>
        <?php foreach($users as $u) : ?>            
            <tr>                
                <td><?php echo $u['id'] ?></td>                
                <td><?php echo $u['name'] ?></td>                
                <td><?php echo $u['age'] ?></td>
                <td><?php echo $u['height'] ?></td>                
                <td><?php echo $u['weight'] ?></td>
            </tr>
        <?php endforeach ?>
        </tbody>
    </table>
</div>

■ jQuery (DataTables)

jQuery(function($){ 
    $.extend( $.fn.dataTable.defaults, {
        // 日本語化 
        language: {
            url: "http://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Japanese.json"
        } 
    });

    $("datatable.table").DataTable({
        order: [ [ 0, "desc" ] ]
    }); 
});

変更後

■ Controller

$_users = Model_User::find('all');

// 取得したデータを配列に入れ直す
$users = [];
foreach ($_users as $u) {
    // 配列に格納 ※連想配列にすると上手く動かなくなるので配列にする
    $users[] = [
        $u['id'],
        $u['name'],
        $u['age'],
        $u['height'],
        $u['weight'],
    ];
}

// JSON 形式でビューにセットする
$this->template->content = View::forge('users', json_encode($users));

■ View

<!-- data属性を使用してJS側にデータを渡す -->
<div class="user-list" data-users="<?php echo $users ?>">
    <table class="datatable table table-bordered table-sorted text-center"></table>

    <!-- tr, td は記述しない -->
</div>

■ Jquey (DataTables)

jQuery(function($){ 
    // data属性からデータを取得
    var users = $('.user-list').data('users');

    $.extend( $.fn.dataTable.defaults, { 
        // 日本語化
        language: {
            url: "http://cdn.datatables.net/plug-ins/9dcbecd42ad/i18n/Japanese.json"
        } 
    }); 

    $("datatable.table").DataTable({
        // data オプションでデータを定義する
        data: users,
        // column オプションで view の th にあたる部分を定義する
        columns: [
            { title: "ID" },
            { title: "名前" },
            { title: "年齢" },
            { title: "身長" },
            { title: "体重" }
        ],
        order: [ [ 0, "desc" ] ]
    }); 
});

これで完成です。

結果

実際に計測したところ、処理速度が1/5にまで短縮されておりました。
ChromeのDevToolsで確認しても如実に表示速度が短縮されていることがわかります。

もちろんカラム数やデータ数で変化は出ると思いますが、目に見えて速くなっていることが確認できたので、効果は絶大だと思います。

もしDataTablesを使用しており、表示速度が遅くて困っていましたら、
ぜひこちらの記事を参考にしていただければと思います。

以上です。


この記事をかいた人

About the author

長谷竜弥

入社4年目です。
システム部に所属しています。
ずっと大阪で勤務していましたが、2019年の11月から横浜開発室に異動になりました。
趣味は野球で休日は草野球をしていましたが、横浜に来てからはできておらず悶々と日々を過ごしております。