【Windows-WSL2】composer install と composer updateでエラー
普段使っているPCとは別のPCで git clone したあとに、PHPUnitを composer install しようとしたときのエラー
環境
- Windows11
- WSL2
- php 7.4.3
エラー文
it is missing from your system. Install or enable PHP's dom extension.it is missing from your system. Install or enable PHP's mbstring extension.
解決手順
composer install しようとしたら下記のエラー
$ composer install
Installing dependencies from lock file (including require-dev)
Verifying lock file contents can be installed on current platform.
Your lock file does not contain a compatible set of packages. Please run composer update.
Problem 1
- phar-io/manifest is locked to version 2.0.3 and an update of this package was not requested.
- phar-io/manifest 2.0.3 requires ext-dom * -> it is missing from your system. Install or enable PHP's dom extension.
Problem 2
- phpunit/php-code-coverage is locked to version 9.2.15 and an update of this package was not requested.
- phpunit/php-code-coverage 9.2.15 requires ext-dom * -> it is missing from your system. Install or enable PHP's dom extension.
Problem 3
- phpunit/phpunit is locked to version 9.5.19 and an update of this package was not requested.
- phpunit/phpunit 9.5.19 requires ext-dom * -> it is missing from your system. Install or enable PHP's dom extension.
Problem 4
- theseer/tokenizer is locked to version 1.2.1 and an update of this package was not requested.
- theseer/tokenizer 1.2.1 requires ext-dom * -> it is missing from your system. Install or enable PHP's dom extension.
To enable extensions, verify that they are enabled in your .ini files:
- /etc/php/7.4/cli/php.ini
- /etc/php/7.4/cli/conf.d/10-opcache.ini
- /etc/php/7.4/cli/conf.d/10-pdo.ini
- /etc/php/7.4/cli/conf.d/20-calendar.ini
- /etc/php/7.4/cli/conf.d/20-ctype.ini
- /etc/php/7.4/cli/conf.d/20-exif.ini
- /etc/php/7.4/cli/conf.d/20-ffi.ini
- /etc/php/7.4/cli/conf.d/20-fileinfo.ini
- /etc/php/7.4/cli/conf.d/20-ftp.ini
- /etc/php/7.4/cli/conf.d/20-gettext.ini
- /etc/php/7.4/cli/conf.d/20-iconv.ini
- /etc/php/7.4/cli/conf.d/20-json.ini
- /etc/php/7.4/cli/conf.d/20-phar.ini
- /etc/php/7.4/cli/conf.d/20-posix.ini
- /etc/php/7.4/cli/conf.d/20-readline.ini
- /etc/php/7.4/cli/conf.d/20-shmop.ini
- /etc/php/7.4/cli/conf.d/20-sockets.ini
- /etc/php/7.4/cli/conf.d/20-sysvmsg.ini
- /etc/php/7.4/cli/conf.d/20-sysvsem.ini
- /etc/php/7.4/cli/conf.d/20-sysvshm.ini
- /etc/php/7.4/cli/conf.d/20-tokenizer.ini
You can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode.Alternatively, you can run Composer with `--ignore-platform-req=ext-dom --ignore-platform-req=ext-dom --ignore-platform-req=ext-dom --ignore-platform-req=ext-dom` to temporarily ignore these required extensions.
Please run composer update とのことなので composer update してみたら下記のエラー
$ composer update
Loading composer repositories with package information
Info from https://repo.packagist.org: #StandWithUkraine
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- phpunit/phpunit[9.5.0, ..., 9.5.19] require ext-dom * -> it is missing from your system. Install or enable PHP's dom extension.
- Root composer.json requires phpunit/phpunit ^9.5 -> satisfiable by phpunit/phpunit[9.5.0, ..., 9.5.19].
To enable extensions, verify that they are enabled in your .ini files:
- /etc/php/7.4/cli/php.ini
- /etc/php/7.4/cli/conf.d/10-opcache.ini
- /etc/php/7.4/cli/conf.d/10-pdo.ini
- /etc/php/7.4/cli/conf.d/20-calendar.ini
- /etc/php/7.4/cli/conf.d/20-ctype.ini
- /etc/php/7.4/cli/conf.d/20-curl.ini
- /etc/php/7.4/cli/conf.d/20-exif.ini
- /etc/php/7.4/cli/conf.d/20-ffi.ini
- /etc/php/7.4/cli/conf.d/20-fileinfo.ini
- /etc/php/7.4/cli/conf.d/20-ftp.ini
- /etc/php/7.4/cli/conf.d/20-gettext.ini
- /etc/php/7.4/cli/conf.d/20-iconv.ini
- /etc/php/7.4/cli/conf.d/20-json.ini
- /etc/php/7.4/cli/conf.d/20-phar.ini
- /etc/php/7.4/cli/conf.d/20-posix.ini
- /etc/php/7.4/cli/conf.d/20-readline.ini
- /etc/php/7.4/cli/conf.d/20-shmop.ini
- /etc/php/7.4/cli/conf.d/20-sockets.ini
- /etc/php/7.4/cli/conf.d/20-sysvmsg.ini
- /etc/php/7.4/cli/conf.d/20-sysvsem.ini
- /etc/php/7.4/cli/conf.d/20-sysvshm.ini
- /etc/php/7.4/cli/conf.d/20-tokenizer.ini
You can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode.
Alternatively, you can run Composer with `--ignore-platform-req=ext-dom` to temporarily ignore these required extensions.
it is missing from your system. Install or enable PHP's dom extension. とのことなので、DOM Extensionをインストールする。
i$ sudo apt-get install php7.4-dom [sudo] password for nakamura: Reading package lists... Done Building dependency tree Reading state information... Done Note, selecting 'php7.4-xml' instead of 'php7.4-dom' The following package was automatically installed and is no longer required: libfwupdplugin1 Use 'sudo apt autoremove' to remove it. The following NEW packages will be installed: php7.4-xml 0 upgraded, 1 newly installed, 0 to remove and 0 not upgraded. Need to get 97.6 kB of archives. After this operation, 447 kB of additional disk space will be used. Get:1 http://archive.ubuntu.com/ubuntu focal-updates/main amd64 php7.4-xml amd64 7.4.3-4ubuntu2.10 [97.6 kB] Fetched 97.6 kB in 1s (68.4 kB/s) Selecting previously unselected package php7.4-xml. (Reading database ... 33161 files and directories currently installed.) Preparing to unpack .../php7.4-xml_7.4.3-4ubuntu2.10_amd64.deb ... Unpacking php7.4-xml (7.4.3-4ubuntu2.10) ... Setting up php7.4-xml (7.4.3-4ubuntu2.10) ... Creating config file /etc/php/7.4/mods-available/dom.ini with new version Creating config file /etc/php/7.4/mods-available/simplexml.ini with new version Creating config file /etc/php/7.4/mods-available/xml.ini with new version Creating config file /etc/php/7.4/mods-available/xmlreader.ini with new version Creating config file /etc/php/7.4/mods-available/xmlwriter.ini with new version Creating config file /etc/php/7.4/mods-available/xsl.ini with new version Processing triggers for php7.4-cli (7.4.3-4ubuntu2.10) ...
からの、 composer update を再度実行。
$ composer update
Loading composer repositories with package information
Updating dependencies
Your requirements could not be resolved to an installable set of packages.
Problem 1
- phpunit/phpunit[9.5.0, ..., 9.5.19] require ext-mbstring * -> it is missing from your system. Install or enable PHP's mbstring extension.
- Root composer.json requires phpunit/phpunit ^9.5 -> satisfiable by phpunit/phpunit[9.5.0, ..., 9.5.19].
To enable extensions, verify that they are enabled in your .ini files:
- /etc/php/7.4/cli/php.ini
- /etc/php/7.4/cli/conf.d/10-opcache.ini
- /etc/php/7.4/cli/conf.d/10-pdo.ini
- /etc/php/7.4/cli/conf.d/15-xml.ini
- /etc/php/7.4/cli/conf.d/20-calendar.ini
- /etc/php/7.4/cli/conf.d/20-ctype.ini
- /etc/php/7.4/cli/conf.d/20-curl.ini
- /etc/php/7.4/cli/conf.d/20-dom.ini
- /etc/php/7.4/cli/conf.d/20-exif.ini
- /etc/php/7.4/cli/conf.d/20-ffi.ini
- /etc/php/7.4/cli/conf.d/20-fileinfo.ini
- /etc/php/7.4/cli/conf.d/20-ftp.ini
- /etc/php/7.4/cli/conf.d/20-gettext.ini
- /etc/php/7.4/cli/conf.d/20-iconv.ini
- /etc/php/7.4/cli/conf.d/20-json.ini
- /etc/php/7.4/cli/conf.d/20-phar.ini
- /etc/php/7.4/cli/conf.d/20-posix.ini
- /etc/php/7.4/cli/conf.d/20-readline.ini
- /etc/php/7.4/cli/conf.d/20-shmop.ini
- /etc/php/7.4/cli/conf.d/20-simplexml.ini
- /etc/php/7.4/cli/conf.d/20-sockets.ini
- /etc/php/7.4/cli/conf.d/20-sysvmsg.ini
- /etc/php/7.4/cli/conf.d/20-sysvsem.ini
- /etc/php/7.4/cli/conf.d/20-sysvshm.ini
- /etc/php/7.4/cli/conf.d/20-tokenizer.ini
- /etc/php/7.4/cli/conf.d/20-xmlreader.ini
- /etc/php/7.4/cli/conf.d/20-xmlwriter.ini
- /etc/php/7.4/cli/conf.d/20-xsl.ini
You can also run `php --ini` in a terminal to see which files are used by PHP in CLI mode.
Alternatively, you can run Composer with `--ignore-platform-req=ext-mbstring` to temporarily ignore these required extensions.
次は it is missing from your system. Install or enable PHP's mbstring extension. とのことなのでインストール。
$ sudo apt-get install php7.4-mbstring [sudo] password for nakamura: Reading package lists... Done Building dependency tree Reading state information... Done The following package was automatically installed and is no longer required: libfwupdplugin1 Use 'sudo apt autoremove' to remove it. The following additional packages will be installed: libonig5 The following NEW packages will be installed: libonig5 php7.4-mbstring 0 upgraded, 2 newly installed, 0 to remove and 0 not upgraded. Need to get 539 kB of archives. After this operation, 1696 kB of additional disk space will be used. Do you want to continue? [Y/n] y Get:1 http://archive.ubuntu.com/ubuntu focal/universe amd64 libonig5 amd64 6.9.4-1 [142 kB] Get:2 http://archive.ubuntu.com/ubuntu focal-updates/universe amd64 php7.4-mbstring amd64 7.4.3-4ubuntu2.10 [397 kB] Fetched 539 kB in 2s (251 kB/s) Selecting previously unselected package libonig5:amd64. (Reading database ... 33180 files and directories currently installed.) Preparing to unpack .../libonig5_6.9.4-1_amd64.deb ... Unpacking libonig5:amd64 (6.9.4-1) ... Selecting previously unselected package php7.4-mbstring. Preparing to unpack .../php7.4-mbstring_7.4.3-4ubuntu2.10_amd64.deb ... Unpacking php7.4-mbstring (7.4.3-4ubuntu2.10) ... Setting up libonig5:amd64 (6.9.4-1) ... Setting up php7.4-mbstring (7.4.3-4ubuntu2.10) ... Creating config file /etc/php/7.4/mods-available/mbstring.ini with new version Processing triggers for libc-bin (2.31-0ubuntu9.7) ... Processing triggers for php7.4-cli (7.4.3-4ubuntu2.10) ..
これで無事 composer update ができた
$ composer update Loading composer repositories with package information Updating dependencies Nothing to modify in lock file Writing lock file Installing dependencies from lock file (including require-dev) Nothing to install, update or remove Generating autoload files 26 packages you are using are looking for funding. Use the `composer fund` command to find out more
参考
composerでPHPUnitがインストールできない - 終電23時15分って早くね?
WSL2にcomposerをインストールするのは下記を参考にした
【PHP】SERVER_NAMEじゃなくてphp_unameで開発環境と本番環境を振り分ける
困ったこと
filter_input(INPUT_SERVER, 'SERVER_NAME')
これでサーバーの名前をとって、 localhost かどうかで振り分けていたが、PHPUnitを使った時に、 null で返ってきたので代替法。
解決策
php_uname('n')
これでPC名がでる。
PHP が稼動しているオペレーティングシステムに関する情報を返す https://www.php.net/manual/ja/function.php-uname
こんな感じになった。
if (mb_strpos(php_uname('n'), '***.localhost') !== false) {
// 開発環境
} else {
// 本番環境
}
参考
【PHP】MAMPでcURLを使えるようにするために
結論
- cacert.pem(CA証明書をダウンロードする)
- php.iniを書き換える
そもそもcURLが使える状況かどうか
php -mで確認phpinfo()で確認
- grepで確認
% php -i | grep cURL cURL support => enabled cURL Information => 7.64.1
curl --versionで確認
% curl --version curl 7.78.0 (x86_64-apple-darwin20.4.0) libcurl/7.78.0 (SecureTransport) OpenSSL/1.1.1k zlib/1.2.11 brotli/1.0.9 zstd/1.5.0 libidn2/2.3.2 libssh2/1.9.0 nghttp2/1.44.0 librtmp/2.3 OpenLDAP/2.5.5 Release-Date: 2021-07-21 Protocols: dict file ftp ftps gopher gophers http https imap imaps ldap ldaps mqtt pop3 pop3s rtmp rtsp scp sftp smb smbs smtp smtps telnet tftp Features: alt-svc AsynchDNS brotli GSS-API HSTS HTTP2 HTTPS-proxy IDN IPv6 Kerberos Largefile libz MultiSSL NTLM NTLM_WB SPNEGO SSL TLS-SRP UnixSockets zstd
→使える環境は整っていそう??
だが、cacert.pemファイルが指定された場所になかったのが原因だった
php - Windows MAMP-PHP CURLの問題
エラー
$curl_error = curl_error($ch) これでエラー内容をキャッチして表示する
“error setting certificate verify locations”
対応策
macのCAファイルの証明書が原因だった。
PHPのcurlでSSL certificate problemが出る場合 | tm23forest.com
- cacert.pem(CA証明書をダウンロードする)
- php.iniを書き換える
MacOS - How to fix curl throwing "error setting certificate verify locations"
証明書が本来あるべき場所にない(または潜在的に読み取れない)と不平を言っている
php.iniの場所を確認
phpinfo() で確認
もういい加減覚えよう。php.iniはどこにあるのか - Qiita
curl.cainfo =" " には、 curl_error($ch) で表示したエラーに「どこにファイルがない!」と教えてくれているので、そのパスをコピペする。
[curl] ; A default value for the CURLOPT_CAINFO option. This is required to be an ; absolute path. curl.cainfo = "/Applications/MAMP/Library/OpenSSL/cacert.pem"
最後に
自分の場合、MAMPをworkspaceにコピーして使用していたため(Railsとかをworkspaceで管理していたためそちらに合わせた)、User/名前/workspace/MAMP/〜の中のphp.iniを変更していたため、変更が反映されなかった。
エラーが教えてくれている通り、Applicationsフォルダの中のphp.iniに追記白しろということだった。
【IoT】IoTシステムのバックエンド(クラウド設計・運用のポイント)
IoTエンジニア養成教本の学習記録です。
機能とサービスの選択
センサネットワークのバックエンドでデータを扱うには下記が必要。
- ディスパッチ(データの受け取り)
- プロセッシング(データ加工などの処理)
- ストアリング(データの保存)
ディスパッチ
デバイスから送られてくるデータを受け取り、適切なプロセッシングに転送する。
- 同時接続数
- 事前の設計時に正確な値を求めるのは難しいため、負荷試験など検証を行って算出するか、大まかな想定接続数を定める。
- 持続的接続

- デバイスの接続エラー処理
プロセッシング
受け取ったデータを保存、分析に適した形式に処理して、ストアリングサービスに渡す。
データを受け取ってすぐに処理するストリーミング処理と、一定の間隔を置いてまとめて処理するバッチ処理がある。
ストアリング
プロセッシングサービスから受け取ったデータを保存する。
【IoT】IoTに最適な通信規格とは(LPWA)
IoTエンジニア養成読本の学習記録です。
LPWAとは
- Low Power Wide Area の略で、消費電力を抑えて遠距離通信が可能なためIoTに特化している仕様。
- 「アンライセンス系(免許不要)」と「ライセンス系(免許必要)」がある。
LoRaWAN(アンライセンス系)
- サブギガ帯と呼ばれる920MHz帯を使う
- 広域通信(数km)
- 規格上では10〜20kmで、最大無線出力(20mA)の実測値は約1.5〜6km
- 低消費電力(20mA程度)
- 送信時の電力が20mAで、待機中は1/100
- 常にDevice主導の通信(Uplinkから通信開始)
- 低データレート(1通信あたりのデータ量=11byte)
- マルチポップ機能はなし
- LoRaゲートウェイに対してLoRaモジュールが紐づくようになる(BLEと同じ)
- IPではなくDev Addr(32bit)で管理
LoRaWANアーキテクチャ

セキュリティ
セルラーなどのように思い認証/暗号化処理はできないため、デバイス、Network Severであらかじめ、Nwskey、Apskeyという事前共有鍵(PSK)を双方で事前共有しておき、通信する際はこの鍵で暗号化の正当性を確認する。
ユースケース
一度に送信できるデータは最大11byteで小さいが、温度、湿度、加速度等のセンシングであれば数バイト程度で事足りるケースが多い。
実装例
LoRaWANモジュール自体は通信モジュールなので、デバイスを制御するためにマイコンが必要。低スペックのマイコンで十分。
各システムの選定と実装のポイント
下記を考慮して総合的に判断する。
1つの方式にこだわるとだいたい無理なデバイス実装、システム構成になるため、複数の通信を組み合わせるのが良い。
- 通信範囲
- データ量
- 通信頻度
- 消費電流
- モビリティの有無(定点か移動か)
- IPの有無
- 通信方向(双方向、片方向)
- 通信量

【IoT】IoTシステムの全体像
IoTエンジニア養成読本の学習記録です。
デバイスをゲートウェイ経由で接続する

データの流れは、「センサデバイス(計測)」→「ゲートウェイ(処理)」→クラウド
- 物理線接続
- 無線接続
ゲートウェイからクラウドへの接続
センサの構成

センサからの信号をCPUで処理するために、OSやライブラリが搭載されている。
- センサ素子
- CPU(マイコン)
センサ素子とCPU(マイコン)が一体化している製品は少数で、センサ素子のみを指してセンサと称している。
どのタイミングで誰がどんなデータを付与するのか
デバイスの能力や数を考慮して設計することが重要。
タイムスタンプを付与する場合、


データフォーマットの例
・固定朝の例
31020170102102030
・カンマ区切り(CSV)の例
31.0,20170102,102030
・JSONの場合
{'temperature': 31.0, 'datetime': '2017-01-02T10:20:30z'}
デバイス選定ガイド
【SQL】ウィンドウ関数で行間比較を行う(相関サブクエリとはバイバイして可読性&パフォーマンスUP)
達人に学ぶSQL徹底指南所の学習記録です。
SQLで同一行内の列同士の値を比較するのはWHERE句で記述すればいいだけだが、異なる行を比較するのは工夫が必要。
SQLで行間比較を行いたいときは、相関サブクエリを使うのが常套手段だったが、相関サブクエリのコードはパフォーマンスと可読性が悪いという欠点がある。
そこで、「行の順列」に基づいて、手続き型言語のループの動作をSQLに持ち込んだのが、ウィンドウ関数。
概要
- 昔は、SQLで行同士を比較するときは、比較対象のテーブルを追加して、相関サブクエリを行なっていた。
- しかし相関サブクエリは、パフォーマンスと可読性が悪い。
- ウィンドウ関数は可読性が高く、パフォーマンス改善も見込める。
- 手続き型のループの動作をSQLに持ち込んだのがウィンドウ関数。
具体例
ある会社の年商を記録するテーブルを考えてみる。
前年と比較する

このテーブルから「前年と比べて年商が増えたのか、減ったのか、変化なしなのか」をSQLで出力してみる。
まずは、「変化なし」の年を取得してみる。
もし手続き型言語で計算するなら、
- 年度で昇順にソートする
- ループさせて1行ずつ直前の行のsale列と比較する
というやり方になるはず。
SQLだとこんな感じ。
// 相関サブクエリを利用 SELECT year, sale FROM sales S1 WHERE sale = (SELECT sale FROM sales S2 where S2.yaer = S1.year - 1) ORDER BY year; year sale ---- ---- 1993 52 1995 50

相関サブクエリで2つのテーブルにおける比較対象の行をズラすことで手続き型のループの代役をしている。
ウィンドウ関数ならこうなる。
// ウィンドウ関数を利用 SELECT year, current_sale FROM (SELECT year, sale AS current_sale, SUM(sale) OVER (ORDER BY year RANGE BETWEEN 1 PRECEDING AND 1 PRECEDING) AS pre_sale FROM sales) AS TMP WHERE current_sale = pre_sale ORDER BY year; year sale ---- ---- 1993 52 1995 50
ポイントは、サブクエリ内部のウィンドウ関数単体で実行するとわかりやすい。
// ウィンドウ関数のみで実行 SELECT year, sale AS current_sale, SUM(sale) OVER (ORDER BY year RANGE BETWEEN 1 PRECEDING AND 1 PRECEDING) AS pre_sale FROM sales; year current_sale pre_sale ---- ------------ -------- 1990 50 1991 51 50 1992 52 51 1993 52 52 1994 50 52 1995 50 50 1996 49 50 1997 55 49
RANGE BETWEEN 1 PRECEDING AND 1 PRECEDING で、「カレント行の年よりも1年前に限定する」という条件で、列を一時的に追加している(フレーム句)。
時系列に歯抜けがない場合
次に、各年について、前年に比べて成長したのか、後退したのか、現状維持なのかを一度に求めてみる(音楽や映画の週間ランキングみたいな)。
// 相関サブクエリを利用 SELECT year, current_sale AS sale, CASE WHEN current_sale = pre_sale THEN '→' WHEN current_sale > pre_sale THEN '↑' WHEN current_sale < pre_sale THEN '↓' ELSE 'ー' END AS var FROM (SELECT year, sale AS current_sale, (SELECT sal FROM sales S2 WHERE S2.year = S1.year - 1) AS pre_sale FROM sales S1) AS TMP ORDER BY year; year sale var ---- ---- --- 1990 50 ー 1991 51 ↑ 1992 52 ↑ 1993 52 → 1994 50 ↓ 1995 50 → 1996 49 ↓ 1997 55 ↑
// ウィンドウ関数を利用 SELECT year, current_sale AS sale, CASE WHEN current_sale = pre_sale THEN '→' WHEN current_sale > pre_sale THEN '↑' WHEN current_sale < pre_sale THEN '↓' ELSE 'ー' END AS var FROM (SELECT year, sale AS current_sale, SUM(sale) OVER (ORDER BY year RANGE BETWEEN 1 PRECEDING AND 1 PRECEDING) AS pre_sale FROM sales S1) AS TMP ORDER BY year; year sale var ---- ---- --- 1990 50 ー 1991 51 ↑ 1992 52 ↑ 1993 52 → 1994 50 ↓ 1995 50 → 1996 49 ↓ 1997 55 ↑
時系列に歯抜けがある場合

年に歯抜けがなければこれでいいが、歯抜けがあると、「今年 - 1」の条件設定ではうまくいかなくなる。より一般化して、「直近」の行を比較対象にする必要がある。
まずは相関サブクエリから。
ある年から見て、「過去の直近の年」ということは、「条件1:自分より前のとしてあること」「条件2:条件1を満たす年の中で最大であること」。
// 相関サブクエリ SELECT year, sale FROM sales2 S1 WHERE sale = (SELECT sale FROM sales2 S2 WHERE S2.year = (SELECT MAX(year) // 条件2:条件1を満たす年の中で最大 FROM sales2 S3 WHERE S1.year > S3.year)) // 条件1:自分より過去 ORDER BY year; year sale ---- ---- 1992 50 1997 55
相関サブクエリだとネストが深くなり、パフォーマンスは劣化する。
ウィンドウ関数ならこうなる。
// ウィンドウ関数を利用 SELECT year, sale FROM (SELECT year, sale AS current_sale SUM(sale) OVER (ORDER BY year ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING) AS pre_sale FROM sales2) AS TMP WHERE current_sale = pre_sale ORDER BY year; year sale ---- ---- 1992 50 1997 55
ウィンドウ関数 VS 相関サブクエリ
- ウィンドウ関数は、サブクエリを使っているが「相関」サブクエリではないので、サブクエリ単体で実行できる。結果、可読性が高く、動作も理解しやすいため、デバッグが簡単。
- テーブルに対するスキャンも一度だけで済むので、パフォーマンスがいい。




