エンジニアとして日々新しい知識をインプットしています。現在の職場には、毎日の終業時に日報を提出する文化があり、その中に「本日発見したこと・気づいたこと」を記載する欄が設けられています。私はこの欄を、業務で得た新しい知見や、業務外の自己学習で学んだことを記録するアウトププットの場として活用しています。この記事は、その日々の学びを知識として定着させ、いつでも振り返れる資産にするために、1ヶ月分をまとめたものです。
2025-2-3 ①
CIワークフローにて、composer installして依存関係をインストールする際に、composer installコマンドに付与を検討しても良いオプションを知ることができました。
composer install –no-progress –prefer-dist –optimize-autoloader
–no-progress:インストール時の進捗バー(プログレスバー)を表示しないオプション。CI環境などでログが煩雑になることを防ぐために使われることが多い。進捗バーが延々と更新されるとログ量が増えるため、それを抑制する目的。
–prefer-dist:依存パッケージをダウンロードする際、可能な限り dist(zip/tarball)を優先するオプション。Gitリポジトリからのcloneよりも、圧縮ファイルのダウンロード&解凍の方が高速に済むケースが多いため、ビルドやテストを高速化できるメリットがある。
–optimize-autoloader:Composerが生成するautoloaderをクラスマップに最適化するオプション。自動ロードを行う際のパフォーマンスを向上させる(特に本番環境や大規模プロジェクトで有効)。通常、PSR-4/PSR-0に従ってディレクトリツリーをたどる形のオートロードを行うが、クラスマップを先にまとめて作っておくことで、クラス読み込みが速くなる。CI環境でも若干テスト実行が高速化される場合があるが、本番運用などで特に効果が大きい(PSR-4/PSR-0といったあたりは理解していません。今は理解する必要ないかなと感じたためです。総じて、読み込みを最適化し、パフォーマンスを向上させる目的のオプションだと理解しました)
2025-2-3 ②
各スタッシュに保存されているファイル名一覧を表示するコマンドを知ることができました。
# 直近のスタッシュ(stash@{0})の変更ファイル名のみを表示
git stash show –name-only
# 特定のスタッシュ(例: stash@{2})の変更ファイル名のみを表示
git stash show –name-only stash@{2}
2025-2-4 ①
Gitの設定でfetch.pruneを有効にしておくと、リモートに存在しなくなったブランチを自動的にローカルからも削除(正確には、リモートトラッキングブランチを削除)することができることを知りました。
git config –global fetch.prune true
- これを設定すると、git fetchのたびにリモートで消えたブランチの追跡ブランチは自動で消えるようになる
- ただし、ローカルブランチ自体は削除されない。あくまでorigin/feature/xxxのリモートトラッキングブランチが削除されるだけ
- 結局ローカルに残っている「feature/xxx」という名前のブランチ自体は手動削除が必要になる
2025-2-4 ②
PHP8以上で利用可能なnull安全演算子について知ることができました。
https://qiita.com/rana_kualu/items/c967d58582ef75e73d7d
2025-2-5 ①
RTK Queryに関して、下記の知見を得ることができました
- useXxxQueryとuseLazyXxxQueryの違いは発火のタイミングだけで、前者はコンポーネントのマウント時に発火する、後者はトリガー関数の実行で発火する
- 発火のタイミングが違うだけということで、同じ引数に対するAPIレスポンス結果は両者間で共通であり、これがストアに保存されることで両者間で共有される
- useXxxQueryにはrefetch機能があり、コンポーネントのマウント時以外でAPIコールを手動で行える
2025-2-5 ②
スタッシュに保存されている変更, 差分を表示するコマンドを知ることができました
# 直近のスタッシュの差分(パッチ)を表示
git stash show -p
# 特定のスタッシュの差分(パッチ)を表示
git stash show -p stash@{2}
2025-2-7
GitHub Actionsを用いたCIワークフローでの自動テストを行う際に、「テストが失敗してもワークフロー全体を成功とみなしたい」という特殊な要件がある場合は、テスト実行ステップに continue-on-error: true という設定を追加すれば、テストが失敗してもジョブ・ワークフローを失敗とせず、成功として扱うことができることを知りました。
2025-2-10 ①
Github Actionsで利用可能なアクションである shivammathur/setup-phpについて知ることが出来ました。
- このアクションは、GitHub Actionsで使われるUbuntuやWindowsなどのベースイメージに、指定バージョンのPHPや拡張モジュール等をインストール&設定するためのアクション
- そのままの “ubuntu-latest” などの仮想マシンには、PHPがインストールされていない場合がある。また、PHPがあってもバージョンや拡張機能が足りない可能性がある
- そこで、shivammathur/setup-php@v2 を使って「指定したバージョンのPHPをインストール」「必要な拡張モジュールの有効化」などを行うことで、テストやビルドに適したPHP環境 を用意することができる
2025-2-10 ②
GitHubのリポジトリ設定で、Automatically delete head branches を ON にすると、PRがマージされたタイミングで自動的にリモートブランチを削除することができることを知りました。
2025-2-12 ①
AWS Cloudformationにて、Type: “AWS::Logs::MetricFilter”によって定義されるcloudwatchメトリクス定義において、MetricTransformationsプロパティに関する知見を深めることができました。
- CloudFormationのAWS::Logs::MetricFilterリソースでは、ログに含まれる文字列パターンを検知し、その検知結果に基づいてCloudWatch メトリクスを発行することができる
- その際に、どのようにメトリクスを作成するかを定義するためのプロパティがMetricTransformations
また、MetricTransformationで定義可能な複数のプロパティの中で、これまで知見のなかったDimensionsとUnitについて知ることができました。
Dimensions:メトリクスに付与するディメンション(ラベル情報)を指定する。CloudWatchメトリクス上でフィルタリングや集計を行うためにディメンションを付けることができる。
(記述例)
Dimensions:
– Name: “LogGroupName”
Value: “!Ref MyLogGroup”
– Name: “CustomDimension”
Value: “MyValue”
Unit:メトリクスに設定する単位(CloudWatchに表示される際の単位)を指定する(指定可能な値の例:Seconds、Bytes、Percent、Count)
まとめ
- MetricTransformationsは、ログからCloudWatchメトリクスを作成する際の「メトリクスの名前・値・単位・ディメンション・デフォルト値」などを定義する場所
- CloudFormationのテンプレート上でログをメトリクスに変換する設定を集中管理できるのがAWS::Logs::MetricFilter(およびMetricTransformationsプロパティ)の役割になる
2025-2-12 ②
下記の設定を行っておくと、毎回のgit fetch時に不要なリモート追跡ブランチが削除され、手動でgit fetch –prune を実行する必要がなくなることを知りました。リモートブランチが削除された場合は、当然それを追跡するリモート追跡ブランチは不要になるため、この設定をすることによりデメリットは特になく、もっと早く知っていれば良かったなと思いました。
git config –global fetch.prune true
2025-2-13
SQLの三値論理について知ることができました。
- SQLでは、bool値として「真(TRUE)」「偽(FALSE)」に加えて「不明(UNKNOWN)」が導入されている
- MySQLもこの三値論理を採用しており、特にNULLが含まれる演算や比較を行うとき、この三値論理(TRUE/FALSE/UNKNOWN)で評価が行われる
(なぜ三値論理が必要か)
従来の二値論理(TRUE/FALSE)では、NULL(値が不明・未定義)を適切に扱うことができない。たとえば、a = 10 という比較式において、aの値がわからない(NULL)の場合、「10と等しい」と判断することも、「等しくない」と判断することもできない。そのため、SQLではこのような「わからない」状態を「UNKNOWN(不明)」という3つ目の値として扱っている。MySQLでは、条件式の結果が UNKNOWN(不明)になった場合、以下のように振る舞う。
- WHERE句における条件式がUNKNOWNの行は返されない(TRUEの行だけ返す)
- CASE WHEN … THEN … END などでも UNKNOWN はTRUEとはみなされない
例:SELECT * FROM table WHERE column = 10;
> columnがNULLのとき条件式はUNKNOWN(不明)になる。WHERE句は結果がTRUEの行だけを返すため、columnがNULLの行は返らない。
2025-2-14
基本的な三値論理の評価ルールについて知ることができました。
式:評価
(単項演算子(NOT))
NOT UNKNOWN:UNKNOWN
(二項演算子(AND))
TRUE and UNKNOWN:UNKNOWN
UNKNOWN and TRUE:UNKNOWN
FALSE and UNKNOWN:FALSE(FALSEと何かをANDすると必ずFALSE)
UNKNOWN and FALSE:FALSE
UNKNOWN and UNKNOWN:UNKNOWN
(二項演算子(OR))
TRUE or UNKNOWN:TRUE(TRUEと何かをORすると必ずTRUE)
UNKNOWN or TRUE:TRUE
FALSE or UNKNOWN:UNKNOWN
UNKNOWN or FALSE:UNKNOWN
UNKNOWN or UNKNOWN:UNKNOWN
2025-2-17
MySQL独自の比較演算子である<=>演算子(NULLセーフ等価比較)について知ることができました。
NULLどうしの比較でもTRUE/FALSEを返す
式:結果
NULL <=> NULL:TRUE
NULL <=> 10:FALSE
10 <=> 10:TRUE
10 <=> 11:FALSE
通常の=演算子では、NULL=NULLはUNKNOWNだが、<=>演算子を使うとTRUEになるという違いがある。NULLを含んだ等価比較を行うときに便利。
2025-2-18
NOT INやIN演算子でNULLが混在していると、思わぬ動きをすることがあることを再認識しました。
例:x NOT IN (1, 2, NULL)
(xが3の場合)3 = NULLはUNKNOWN。つまり、(3 = 1) OR (3 = 2) OR (3 = NULL) は FALSE or FALSE or UNKNOWN となる。FALSE or FALSE or UNKNOWN は UNKNOWNとなり、最終的に NOT UNKNOWN も UNKNOWN になるため、条件は TRUE とはみなされない(行は取得されない)。このように、NULL が要素として入っている NOT IN は、意図せず行がフィルタされてしまうことがあるので注意が必要。実際には NULL が含まれる可能性のある列に対しては、NOT IN ではなく LEFT JOIN や NOT EXISTS を使うなど、より明示的な書き方が好まれることがある。
2025-2-19
ストアドプロシージャ(Stored Procedure)について知ることができました。
- ストアドプロシージャとは、データベース上で実行される一連のSQL文やロジックを、ひとまとまりにして定義しておく仕組みのこと
- アプリケーション側から複数回呼び出すような処理をまとめておくことで、再利用性を高めたり、実行速度を向上させることができる
(主なポイント)
1. サーバーサイドで動作
- ストアドプロシージャはRDBサーバー上で動作する
- 通常のSQLクエリは都度アプリケーションが投げかけるが、ストアドプロシージャを使うと、データベースサーバーが直接、その処理ロジックを保持して実行できる
2. パラメータを受け取れる
- ストアドプロシージャは引数を設定することができる
- アプリケーション側はパラメータを指定して呼び出すだけで、中で複雑なSQL文を実行することができる
3. ビジネスロジックの切り出し
- アプリケーションのビジネスロジックのうち、データベースに深く関わるものをストアドプロシージャにまとめることで、クライアント側のコードをシンプルに保てる場合がある
- 例えば、売上集計、メッセージ集計など、複数テーブルにまたがる集計ロジックをまとめたりする
4. 保守性とパフォーマンス
- 保守性:ロジックが一箇所にまとまるため、変更を行う際もストアドプロシージャ内で修正すればよいため、保守が行いやすい面がある
- パフォーマンス:RDBごとに最適化が行われ、ネットワーク越しに大量のSQLを投げるより高速に処理できることがある。また一度コンパイルされた実行計画を再利用しやすい仕組みもあるため、複数回呼び出す処理の効率が向上する場合がある
2025-2-21
Segfault(セグメンテーションフォルト)というものについて知ることができました。
Segfaultとは、プログラムがメモリに不正なアクセスをした際にOSから強制的に終了させられるエラーのこと。例えば、存在しないメモリ領域を読みに行ったり、書き込んではいけない領域に書き込みを行ったりすると、OSは「そのメモリは使えない」と判断してプログラムを強制終了する。その結果、「Segmentation fault(セグフォ)」というエラーが発生する。
Segfault の具体例
・NULLポインタの参照
・範囲外の配列要素へアクセス
・リソースの解放後に再度アクセスするダングリングポインタの使用
・実行コード領域や読み取り専用領域への書き込み
これらの動作が原因で、プログラムが意図しないメモリアクセスを行い、結果的にOSによりプロセスが終了させられる
2025-2-25
MySQLのトリガー定義において、DELIMITERの役割について知ることができました。
(コード例)
DROP TRIGGER IF EXISTS after_message_thread_update;
DELIMITER //
CREATE TRIGGER after_message_thread_update
AFTER UPDATE ON message_thread
FOR EACH ROW
after_message_thread_update_trigger: BEGIN
# トリガー処理定義
END
//
DELIMITER ;
通常、セミコロンを区切りとしてSQL文を実行するが、トリガー定義のように複数行にわたるステートメント内ではセミコロンを使用することがある。そこで、DELIMITERを使う。上記コードでは、DELIMITERにより、一時的に区切り文字を//に変更している。トリガーの定義が終わったあと、再びDELIMITERをセミコロンに戻している。
2025-2-26 ①
GitのDependabotについて知ることができました。
Dependabotとは、GitHubの機能として利用できるサービスであり、プロジェクト内の依存関係に含まれる脆弱性やアップデートの有無を検知して自動でPRを作成したり、アラートを出すことができるサービスのこと
2025-2-26 ②
MySQLのトリガー定義にて、DROP TRIGGER IF EXISTS ~を先に実行してからCREATEする運用が多い理由について知ることができました。
- MySQL(およびMariaDB)では、同じテーブル・同じタイミング(INSERT/UPDATE/DELETE)に対して、同名のトリガーを重複して定義することができない
- そのため、トリガーを作成するスクリプトなどを実行する際、既に同名のトリガーが存在するとエラーになってしまう
- そこで、既に同名のトリガーが存在する場合は、削除してからCREATEする
2025-2-28
QEMUエミュレーションについて知ることができました。
QEMU(Quick EMUlator)とは、異なるCPUアーキテクチャのバイナリをエミュレーションによって実行するためのソフトウェア。たとえば、ARMマシン上でx86用プログラムを動かす場合、通常はCPUの命令セットが違うためそのままでは実行できない。そこでQEMUなどのエミュレータを使い、ソフトウェア的にx86命令をARMの命令へ変換しながら実行する。これは「エミュレーション」と呼ばれ、オーバーヘッドは発生するが、通常はプログラムが動くように補ってくれる。