1on1で気をつけている7つのこと
みなさんの会社では1on1はやっていますか?
私の会社では会社の仕組みとして1on1をやっています。 1on1って何すれば良いの?という方のために私がメンターとして1on1を運営する中で気をつけていることをまとめたいと思います。
これがきっかけで1on1を始められる方が増えて現場が円滑になれば良いな。
7つのことと書いていますが多分増えます。今は絞り出して7つだった。
1on1の目的
- 業務上困ったことを相談したりする場
- 目標の振り返り、確認の場
- 雑談
基本的には、業務なので業務中心の話をします。とはいえ、他の話をしたり聞いたりして現在どういう状況なのか?ということを知っておくことは大切です。
1on1をする上で気をつけていること
- あなただけの時間ですよ
- メンターをやる人は多分忙しい、ミーティングも多い、気軽に声をかけるのがはばかられることもある
- だからこそ、1on1をしているときはあなただけの時間です、というのが重要
- PCは見ないし、スマホもいじりません(議事録は取るけど)
- 緊急の場合は必ず一言断ってから
- 必ず閉鎖空間で行う
- 変な意味ではなく、何を言っても誰にも聞かれない、という空間を作る
- 恥ずかしいこと、他人に聞かれたくないことを言いやすくなる
- 例えば、「昇進したいです!」とはオープンな場では言いにくい
- ミーティングルームが取れない場合は次週にスキップするくらい大切にしている
- 否定しない
- (なんだかテクニックみたいで嫌だけど、)否定されたら普通は次相談しようとは思わない
- 否定されたがっている人以外は普通は嫌だ。自分も嫌だ。
- 一緒に考える、提案する
- 命令されたら業務、業務の一環だけど業務じゃない(表現が難しい)
- 答えを渡すのではなく一緒に作る。なので同じ問題でも解決策が人それぞれになる
- 毎回決まったフォーマットを利用している
- 何を聞かれるのかわからないのは不安なので大体なにを聞かれるかを予測できるようにする
- アジェンダは毎回共有すると良い
- 前回話したことを踏まえた上でアジェンダを作る
- 前回〇〇について話していたけど今はどう?
- 一回きりではなく連続していることを意識する
- というより問題解決が目的なら決着するまで追いかける
- 不満があるなら現在どうかを確認する
- 同じペースで行う
- 必要に応じて回数は増やしても減らすことは基本的にない
- ただしそもそものペースを落とすことはある
- 業務の一環でやっているので雑談しかしてなくても業務
1on1をやってみて
- メンティーの成長はもちろんメンターも成長する(かもしれない)
- 本当は業務に直接関係ない人ともやると新鮮なんだろうな、とは思う
1on1を始める前に読んだ本
- ここに書いてあることをできるところから実践していった
シリコンバレー式 最強の育て方 ― 人材マネジメントの新しい常識 1 on1ミーティング―
- 作者: 世古詞一
- 出版社/メーカー: かんき出版
- 発売日: 2017/09/13
- メディア: 単行本(ソフトカバー)
- この商品を含むブログを見る
MySQLについていろいろ書いてみる
まずはRDB共通なものを書いてMySQLのことを挟んでいく。自分用のメモとして眠っていたものを転載。
ACIDとトランザクション
- ACIDとは
- 原子性 (Atomicity)
- 一貫性 (Consistency)
- 分離性 (Isolation)
- 持続性 (Durability)
- ACIDはトランザクションの概念と密接に結びついている
- トランザクションを保証する概念
- トランザクションは、独立していて、確定すると継続され、ALL OR NOTHINGで一貫しているもの
- 特に複数のテーブルを更新しているときには矛盾が発生する危険がある
トランザクション分離レベル
- ACIDのIのこと
- MySQL(InnoDB)がサポートしているのは以下のレベル
- ただし、分離レベルによらず、SQL文の実行以外、整合性制約をチェックするときのスキーマ定義の暗黙の読み込みや、参照整合性制約によって実行される参照動作の実行において、P1〜P3(後述)は発生しない
- 上に行くほど、並列性が低い代わりにデータの一貫性、結果の再現性が高い
- 詳細は以下の通り
- ただし、InnoDBは
REPEATABLE READ
でもファントムリードが発生しないことになっている
ダーティリード | ファジーリード | ファントムリード | |
---|---|---|---|
READ UNCOMMITTED | 発生する | 発生する | 発生する |
READ COMMITTED | 発生する | 発生する | |
REPEATABLE READ | 発生する | ||
SERIALIZABLE |
ここが詳しい https://qiita.com/PruneMazui/items/4135fcf7621869726b4b
- それぞれの分離レベルで
SERIALIZABLE
から離れれば離れるほど読み取り時に不整合が発生しやすい - それぞれの読み取り不整合がなんなのか
ダーティリード(P1)
ファジーリード(P2)
- 別のトランザクションで更新されたデータを読むことにより、一貫性がなくなる現象
- つまり自分がコミットする前に、更新されたデータが更新前後で異なる値として取得される
ファントムリード(P3)
他にも
ダーティーライト(P0)
- トランザクションT1がデータを更新しトランザクションT2がT1がコミットかロールバックを実行する前に同じデータを更新する。このとき、T1とT2のどちらかがロールバックを実行すると正しいデータの値は何であるべきか不明確になる
失われた更新(ロストアップデート)(P4)
- 例外的
- トランザクションT1がデータを読み出す。T2がそのデータを更新する。最後にT1がT2が更新した値の前に基づいてデータを更新しコミットする。T2の更新が消える。
CURSOR STABILITY分離レベル
- というものが存在しているが、
READ COMMITTED
のSQLカーソルに対するロック動作なので割愛
ロック
- MySQLには、というよりDBにはロック機構が存在している。理由は、マルチユーザーで単一のリソースにアクセスするのでリソース競合が発生するため。正しく更新(INSERT,UPDATE,DETELE)されるようにするための仕組みがロック
- MySQLのロック
- ロックの種類( https://dev.mysql.com/doc/refman/5.6/ja/innodb-record-level-locks.html )
- レコードロック
- クラスタインデックスを使って取得されるロック
- 更新対象のレコードのみロックできれば最も理想的なロックになる
- ギャップロック
- インデックスレコード間のギャップ、先頭インデックスレコードの前や末尾インデックスレコードのあとのギャップをロックする仕組み
- キーを指定して以上とかでロックをかけるとほぼテーブルロックとかになる怖いやつ
- ネクストキーロック
- ロッキングリードにおいてファントムを防ぐために用いられる仕組み
- これは行ロックとギャップロックを組み合わせたもの
- ロック対象の次の値までをロックすることでファントムリードを防ぐ(ファントムリードは別トランザクションで挿入されたデータが見えてしまう現象のため)
select ~ for update
でロックした場合、データが挿入できなければファントムリードは防げる。ただし、並列性はSERIALIZABLE
ほどではないがプレーンなREPEATABLE READ
よりは下がる
- レコードロック
- 専有レベル(lock mode)
- ロックの種類( https://dev.mysql.com/doc/refman/5.6/ja/innodb-record-level-locks.html )
MVCC(multi version concurrency control)
- 読み取り専用のトランザクションにおいて、若干の時差を許容することで一貫性のある読み取りを実現するための仕組み
- InnoDBの専売特許ではなく、Oracle、PostgreSQLにも存在するらしい( https://ja.wikipedia.org/wiki/MultiVersion_Concurrency_Control )
- InnoDBでは、
REPEATABLE READ
、READ COMMITTED
で利用されている - InnoDBではこれがあるため、ファントムリードが起きないことになっている
- ただし、このことが別の問題を引き起こしている
ノンロッキングリードとロッキングリード
- MVCCはノンロッキングリードでしか用いられない
- ノンロッキングリードとは?
- ノンロッキングとは行にロックをかけないという意味
- ロッキングは行にロックをかける
- これは、
select ~ for update
もしくはselect ~ lock in share mode
を使うか否かによって取得される結果が異なるということである - ノンロッキングリードで読み取られるのは古いバージョンのデータなので、最新のデータが何であろうと、ロックされていようがいまいが構わない。そのような場合でしか、MVCCは用いられない。
- つまりは、MVCCはリード性能を高めるための仕組みであって更新時には問題を起こす可能性がある
- ファントムリード(別のトランザクションで挿入されたデータが見えること)が防げているのはノンロッキングリードのときのみでロックありでリードするロッキングリードの場合はMVCCの対象から外れて最新のデータが見える(つまりはファントムリードが発生する)
インデックス
- InnoDBはクラスタインデックスという構造を採用している
- クラスタインデックスはデータがインデックスのリーフノード上に格納されている
- Oracleみたいにインデックスとデータ領域が分かれているわけではない(今は知らん)
- 主キーのインデックス上にデータが存在している。そのため、主キー検索すると爆速(一回の走査でデータも取れちゃうため)
- あとはセカンダリインデックスというものがある。
- これがいわゆるインデックスというもの。
- 独自に指定して作成するインデックス(
create index ~
で作成されるインデックス)はすべてこれ - セカンダリインデックスを使う場合は、セカンダリインデックスを走査してからクラスタインデックスを走査するので効率が悪い
- とは言ってもそういう仕組みのDBだってあるしそこまで問題にはならないのでは?
- 複合インデックスを用いたカバリングインデックスとかを使うと効率上がる(インデックスだけ見れば良いので)
- とは言え、インデックス設定しまくるのは良くないのでご利用は計画的に。(インデックスショットガン)
オンラインDDL
- MySQL5.6から一部のDDLがオンラインで実行できるようなった(書き込みでロックが発生しなくなった)
- 少なくともインデックス作成はオンラインでできる。ただし、IO負荷やCPU負荷は考慮すること
- 力尽きたのであとは以下のリンクを参照してください
docker環境にPythonの実行環境を用意する
Macでgensimが読み込めないエラーが発生していた件で、問題の切り分けのためにDockerを使ってPythonの実行環境を作成してそこで色々試してみた話 結局、ライブラリを最新版より1つ古いものを使うようにすれば良いという結果になったけどクリーンな環境をサクッと用意できるのはDockerのメリットだなーと実感した。
参考にした、というよりほぼこちらの内容のまま(ありがとうございます) qiita.com
Dockerfile
FROM python:3 USER root RUN apt-get update RUN apt-get -y install locales && \ localedef -f UTF-8 -i ja_JP ja_JP.UTF-8 ENV LANG ja_JP.UTF-8 ENV LANGUAGE ja_JP:ja ENV LC_ALL ja_JP.UTF-8 ENV TZ JST-9 ENV TERM xterm RUN apt-get install -y vim less RUN pip install --upgrade pip RUN pip install --upgrade setuptools
docker-compose.yml
version: '3' services: python3: restart: always build: . container_name: 'python3' working_dir: '/root/' tty: true volumes: - ./:/root/
Dockerfileとdocker-compose.ymlがあるディレクトリで以下のコマンドを実行
$ docker-compose up -d --build $ docker exec -it python3 bash
コンテナの中に入る。
試したかったのはgensim
なのでこれだけインストール
$ python -m pip install gensim # 実際は $ python -m pip install gensim==3.5.0
Dockerfileに含めておきたいときはこんな感じ
RUN pip install --no-cache-dir gensim==3.5.0
--no-cache-dir
オプションがないとValueError: numpy.ufunc has the wrong size, try recompiling. Expected 192, got 216
のエラーが出る
gensimの読み込みで実行時エラーが発生する
意外と日本語で検索にヒットしないのでメモ。
発生したエラーはこんな感じ
>>> from gensim.models import word2vec Traceback (most recent call last): File "<stdin>", line 1, in <module> File "/usr/local/lib/python3.7/site-packages/gensim/__init__.py", line 5, in <module> from gensim import parsing, corpora, matutils, interfaces, models, similarities, summarization, utils # noqa:F401 File "/usr/local/lib/python3.7/site-packages/gensim/corpora/__init__.py", line 6, in <module> from .indexedcorpus import IndexedCorpus # noqa:F401 must appear before the other classes File "/usr/local/lib/python3.7/site-packages/gensim/corpora/indexedcorpus.py", line 15, in <module> from gensim import interfaces, utils File "/usr/local/lib/python3.7/site-packages/gensim/interfaces.py", line 21, in <module> from gensim import utils, matutils File "/usr/local/lib/python3.7/site-packages/gensim/matutils.py", line 1076, in <module> from gensim._matutils import logsumexp, mean_absolute_difference, dirichlet_expectation File "__init__.pxd", line 872, in init gensim._matutils ValueError: numpy.ufunc has the wrong size, try recompiling. Expected 192, got 216 >>>
インストールされているバージョンは 3.6.0
$ pip show gensim Name: gensim Version: 3.6.0 Summary: Python framework for fast Vector Space Modelling Home-page: http://radimrehurek.com/gensim Author: Radim Rehurek Author-email: me@radimrehurek.com License: LGPLv2.1 Location: /usr/local/lib/python3.7/site-packages Requires: scipy, numpy, six, smart-open Required-by:
バージョンを一個前(3.5.0
)に戻したらエラーが消えた
$ pip install gensim==3.5.0
そもそも他の人でも起きているのか謎い。。 ただ、Docker環境を作って検証したけど発生したのできっと他にも困っている人がいるはず!
MySQLのインデックスは1つのテーブルにつき1つしか使われないとは限らない
タイトルが全てですが、その通り。 MySQLにはインデックスマージというものが存在するということを最近知った。
詳細は以下のドキュメントを参照してほしい。
MySQL :: MySQL 5.6 リファレンスマニュアル :: 8.2.1.4 インデックスマージの最適化
必ずしも使われるわけではないけど、1つのテーブルにつきインデックスは1つしか使われないものと思っていた認識が誤りだった。
create table user( id int, last_name varchar(20), first_name varchar(20), nickname varchar(20) ) ENGINE = InnoDB DEFAULT CHARSET = utf8;
こんな感じのテーブルがあるとしてインデックスを貼ります。
CREATE INDEX idx_first_name ON user(first_name); CREATE INDEX idx_last_name ON user(last_name); CREATE INDEX idx_nickname ON user(nickname);
データを何件か入れて以下のSQLを実行して実行計画を取得する。
explain select * from user where first_name like 'テスト%' or last_name like 'テスト%' or nickname like 'テスト%';
インデックスを貼っていない場合
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | user | ALL | NULL | NULL | NULL | NULL | 200 | Using where | +------+-------------+-------+------+---------------+------+---------+------+------+-------------+
インデックスを貼っている場合
+------+-------------+-------+-------------+-------------------------------------------+-------------------------------------------+----------+------+------+--------------------------------------------------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-------+-------------+-------------------------------------------+-------------------------------------------+----------+------+------+--------------------------------------------------------------------------+ | 1 | SIMPLE | user | index_merge | idx_first_name,idx_last_name,idx_nickname | idx_first_name,idx_last_name,idx_nickname | 63,63,63 | NULL | 3 | Using sort_union(idx_first_name,idx_last_name,idx_nickname); Using where | +------+-------------+-------+-------------+-------------------------------------------+-------------------------------------------+----------+------+------+--------------------------------------------------------------------------+
では、複合インデックスだとどうなるか?既存のインデックスを消して以下のインデックスを追加し、確認する
CREATE INDEX idx_multi ON user(first_name, last_name, nickname);
+------+-------------+-------+------+---------------+------+---------+------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +------+-------------+-------+------+---------------+------+---------+------+------+-------------+ | 1 | SIMPLE | user | ALL | idx_multi | NULL | NULL | NULL | 200 | Using where | +------+-------------+-------+------+---------------+------+---------+------+------+-------------+
なるほど。or
で検索する場合は、複合インデックスを使っても使われることはなく1つ1つのカラムに対してインデックスを貼ることでインデックスマージが効いてパフォーマンスが上がる可能性が高いということらしい。
今回のケースでは Using sort_union
が使われているが公式ページを見ると他にも種類があるようです。
今回の機能はMySQL5以降は有効とのことでMariaDBとMySQL両方で試してみました。こうゆうとき、dockerとか便利ですよね〜と言いたいとこだったけど最新版のMariaDBでエラーが発生して時間かかった。結局バージョンを10.0
まで落とすことで解決したけど。
docker-compose.yml
version: '2' services: maria: image: mariadb:10.0 restart: always volumes: - ./data/mariadb/:/var/lib/mysql ports: - "3307:3306" expose: - "3307" environment: MYSQL_ROOT_PASSWORD: root user: "1000:50" mysql: image: mysql restart: always volumes: - ./data/mysql:/var/lib/mysql ports: - "3308:3306" expose: - "3308" environment: MYSQL_ROOT_PASSWORD: root
mariadb:10.2
で出ていたエラーは以下の通り。時間があったら調べよう
[Warning] InnoDB: Failed to set O_DIRECT on file./ibdata1;OPEN: Invalid argument, ccontinuing anyway. O_DIRECT is known to result in 'Invalid argument' on Linux on tmpfs, see MySQL Bug#26662. [Note] InnoDB: Highest supported file format is Barracuda. [Note] InnoDB: 128 out of 128 rollback segments are active. [Note] InnoDB: Creating shared tablespace for temporary tables [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ... [Note] InnoDB: File './ibtmp1' size is now 12 MB. [Note] InnoDB: Waiting for purge to start [Note] InnoDB: 5.7.21 started; log sequence number 1603633 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool [Note] InnoDB: Buffer pool(s) load completed at 180304 4:52:55 [Note] Plugin 'FEEDBACK' is disabled. [ERROR] Could not open mysql.plugin table. Some plugins may be not loaded [Note] Recovering after a crash using tc.log [ERROR] Can't init tc log [ERROR] Aborting