dak ブログ

python、rubyなどのプログラミング、MySQL、サーバーの設定などの備忘録。レゴの写真も。

MySQL で delete 中に select を実行した場合の挙動を確認

2021-04-29 12:26:15 | mysql
MySQL (innodb) で delete 中に select を実行した際に、select がロックされるかを確認したメモ。
以下の例で、select はロックされない、select ... for update はレコード単位でロックされることが確認できました。

以下のテーブルを作成して、レコードを登録しておきます。
create table test_lock (
       id    varchar(100),
       r     int,
       primary key(id),
       index (r)
);


■実験1
以下の delete+10秒のスリープ のトランザクションを実行中に select を行い、
delete のトランザクション完了する前に select の実行結果が得られるか調べます。
begin;
  delete from test_lock where r >= 900;
  select sleep(10);
commit;


begin;
  select * from test_lock where r >= 900 limit 10;
commit;

実行してみると、delete によってロックされずに select の結果が得られることが確認できました。

■実験2
一方、以下の select ... for update の場合には、delete のトランザクション終了後に
select の実行が完了しました。
begin;
  select * from test_lock where r >= 900 limit 10 for update;
commit;


■実験3
上記の delete、select はともに r >= 900 の条件で同一レコードを参照していますが、
select の条件を変更して delete の対象と重ならないようにすると、delete によってロックされずに
select の結果が得られます。
begin;
  select * from test_lock where r <= 100 limit 10 for update;
commit;


MySQLでランダムにレコードを検索する方法

2021-04-29 01:37:59 | mysql
MySQLでランダムにレコードを検索する方法のメモ。

MySQLでランダムにレコードを検索するには order by rand() を指定します。
例えばランダムにレコードを10件取得するには以下のような select 文になります。

■方法1
select
	*
from
	table
order by
	rand()
limit 10
;

乱数をあらかじめレコードに付与しておくことで、ランダムにレコードを選択することもできます。

■方法2
create table rand (
	id	varchar(100),
	r	float,
	primary key(id),
	index (r)
);

select
        id
from
        rand
where
        r >= rand()
order by
        r asc
limit 10
;

10万件のレコードを登録しておいて、方法1と方法2の実行時間を調べたところ、
方法1は0.06秒、方法2は0.00秒という結果になりました。

nmslib でインデックスを生成する際のスレッド数の指定方法

2021-04-01 00:21:49 | python
nmslib でインデックスを生成する際のスレッド数の指定方法のメモ。

nmslib の createIndex() でパラメータを指定しないと、CPUをフルに使おうとしてくれるのですが、
他のプロセスに CPU を回せなくなることもあります。

createIndex() では indexThreadQty でスレッド数を指定することができます。
index = nmslib.init(method='hnsw', space='l2')
index.createIndex({'indexThreadQty': スレッド数})