クラウドワークス エンジニアブログ

日本最大級のクラウドソーシング「クラウドワークス」の開発の裏側をお届けするエンジニアブログ

2023年 crowdworks.jp の SRE チームでやったこと

この記事は クラウドワークス Advent Calendar 2023 シリーズ1 6日目の記事です。

こんにちは。crowdworks.jp SRE チームの田中(@kangaechu)です。 この記事では crowdworks.jp の SRE チームが2023年にやったことを記載していきます。 やっていることは色々で、まとまりはありませんが、そこら辺はご容赦ください。

  • 2022年の振り返り
  • 2023年にやったこと
    • CircleCI インシデント対応
    • RundeckのECS化
    • Railsで使用しているMemcachedをRedisに寄せる
    • MySQL 8.0 アップデート
    • Redshift AQUA化
    • メール
    • SRE NEXT 2023
  • まとめ

2022年の振り返り

去年までにどのようなことをしてきたかはこの記事を参照ください。

engineer.crowdworks.jp

2023年にやったこと

続きを読む

本業、副業、趣味でソフトウェア開発している話

この記事は クラウドワークス Advent Calendar 2023 シリーズ 1の2日目の記事です。

こんにちは。crowdworks.jp でエンジニアをしている高橋です。

この記事は本業、副業、趣味でソフトウェア開発をしていて感じたことや経験を振り返ったポエムになります。技術的な要素はなく、働き方の話がメインになります。

はじめは、個人のブログや個人利用の文章共有サービスにて書き残そうと思いましたが、フリーランスや副業関連のサービスを提供している側の会社に所属していることもあり、現在の状況について、誰かの参考になればと思い、クラウドワークスのエンジニアブログに書き残すことにしました。

続きを読む

今年の汚れ、今年のうちに!MySQLで使っていないインデックスを削除しよう

この記事は クラウドワークス Advent Calendar 2023 シリーズ2 2日目の記事です。

こんにちは。crowdworks.jp SRE チーム 田中(@kangaechu)です。 年末といえば大掃除ですね。 皆さんのデータベースにも使っていないインデックスが溜まっていませんか? お掃除してきれいな新年を迎えましょう。

手順

1. MySQLで使っていないインデックスの一覧を取得

未使用のインデックスは sys.unused_indexes ビューで確認できます。

dev.mysql.com

しかし、このビューの元データである performance_schema テーブルは起動時から終了時までのデータしか保持していません。

Tables in the Performance Schema are in-memory tables that use no persistent on-disk storage. The contents are repopulated beginning at server startup and discarded at server shutdown.

https://dev.mysql.com/doc/refman/8.0/en/performance-schema.html

そのため、長期間起動した状態のDBインスタンスを準備しましょう。

-- 未使用のインデックスを確認
SELECT
  object_name,
  index_name
FROM
  sys.schema_unused_indexes
WHERE
  object_schema = 'test'
ORDER BY
  object_name,
  index_name;

2. 削除してはいけないインデックスを除外

sys.unused_indexes ビューには、削除してはいけないインデックスも含まれています。 今回対象となったのは、FOREIGN KEY 制約を持つインデックスです。

MySQLのドキュメントにはFOREIGN KEY 制約とインデックスの関係について、以下のような記述があります。

MySQL requires indexes on foreign keys and referenced keys so that foreign key checks can be fast and not require a table scan. In the referencing table, there must be an index where the foreign key columns are listed as the first columns in the same order. Such an index is created on the referencing table automatically if it does not exist. This index might be silently dropped later if you create another index that can be used to enforce the foreign key constraint. index_name, if given, is used as described previously.

https://dev.mysql.com/doc/refman/8.0/en/create-table-foreign-keys.html

  • FOREIGN KEYのチェックを高速化し、テーブルスキャンを必要としないように、FOREIGN KEYと参照キーのインデックスが必要
  • 参照テーブルには、FOREIGN KEY列が同じ順序で最初の列としてリストされるインデックスが必要
  • このようなインデックスが存在しない場合は、参照テーブルに自動的に作成される

つまり、

-- parent table
CREATE TABLE parent(id int PRIMARY KEY, name varchar(20));

-- child table
CREATE TABLE child(id int PRIMARY KEY, name varchar(20), parent_id int,
 INDEX index_child_parent_id(parent_id),
 FOREIGN KEY fk_child_parent_id(parent_id) REFERENCES parent(id)
);

このようなテーブルがある場合、child テーブルの parent_id 列にはインデックスが必要です。 そのため、 index_child_parent_id を削除しようとすると、インデックスが未使用であってもエラーになります。

mysql> DROP INDEX index_child_parent_id ON child ALGORITHM=INPLACE LOCK=NONE;
ERROR 1553 (HY000): Cannot drop index 'index_child_parent_id': needed in a foreign key constraint

そのため、これらのインデックスは削除対象から除外しましょう。

3. インデックスをinvisibleに変更

削除対象が決まったところで、インデックスを削除したいところです、がやっぱり怖いですよね。 そんなあなたに朗報です。

MySQL 8.0からInvisible Indexという機能が追加されました。 これはインデックスをInvisible(=不可視)にできるという機能です。 レコードの追加・変更・削除時にインデックスは更新されますが、オプティマイザはそのインデックスを使いません。

  • インデックス削除
  • → 実は使ってたのでパフォーマンス悪化
  • → 慌ててインデックス作成
  • → インデックス作成時にリソースを消費し、パフォーマンス悪化

みたいなことがないように、試しにオプティマイザがインデックスを使わない設定を試すことができます。

ALTER TABLE child ALTER INDEX index_child_parent_id INVISIBLE, ALGORITHM=INPLACE, LOCK=NONE;

4. インデックスを削除

インデックスをinvisibleにして問題ないことが確認できたら、実際に削除しましょう。

DROP INDEX index_child_parent_id ON child ALGORITHM=INPLACE LOCK=NONE;

このクエリでは ALGORITHM=INPLACE を指定していますが、これは クエリ実行時に使用するアルゴリズムを指定しています。 指定しない場合、INSTANTINPLACE → COPYの順に適用されます。 指定した場合、そのアルゴリズムが使えない場合には失敗します。

dev.mysql.com

今回は意図しない処理およびロックを防ぐため、明示的に指定しています。 オペレーションごとに指定可能なアルゴリズムはドキュメントに記載があります。 今回はOnline DDL Operations - Dropping an indexを参照し、In PlaceYes だったため、 INPLACE を指定しています。

dev.mysql.com

記述が重複するため詳細な説明は省きますが、LOCKALGORITHM と同様に指定しています。

まとめ

「テーブルを作ったし、とりあえずインデックスを張っておこう」という理由でインデックスを作成することはよくあるかと思います。 しかし、無駄に作成されたインデックスはレコード追加・変更・削除時にコストが発生し、リソースを消費します。

この対応により、crowdworks.jpではセカンダリインデックスの20%以上を削除することができました。

統計情報の変更やバージョンアップなどにより、実行計画は変化していくため、必要なインデックスは随時変化します。 不要なインデックスは削除し、必要なインデックスを作成しやすい環境を構築していきたいと思います。

crowdworks.jp のフロントエンド活動を振り返る2023

アイキャッチ:アイキャッチ:crowdworks.jp のフロントエンド活動を振り返る2023

この記事はクラウドワークス Advent Calendar 2023 シリーズ 1の1日目の記事です。

クラウドソーシングサービス「クラウドワークス」(以下 crowdworks.jp )にてエンジニアをしております、フロントエンドの可能性をしつこく信じ続ける@okuto_oyamaです。

一昨年・去年と引き続き、今年もアドベントカレンダー初日の盛り上げ手としてやっていきます。よろしくお願いします。

フロントエンド活動の振り返りをしてみよう

一昨年・去年もフロントエンド活動の振り返りをしてみましたが、今年もやっていきます。

qiita.com

engineer.crowdworks.jp

続きを読む

MemcachedからRedisに変更しました

アイキャッチ:MemcachedからRedisに変更しました

はじめに

こんにちは、クラウドワークス (https://crowdworks.jp/) でエンジニアをしているBugfireです。今回は所属しているジャンヌチームと、協力しているSREチームにおける活動をお伝えします。

クラウドワークスでは、AWS上でRailsアプリケーションを運用しており、以前はMemcachedとRedisの両方をKVSとして利用していました。最近、より効率的な運用を目指してRedisに統合しました。

続きを読む

© 2016 CrowdWorks, Inc., All rights reserved.