①INDEX なし CREATE TABLE t1noindex (id int PRIMARY KEY, uuid VARCHAR(40) NOT NULL, date_created timestamp NOT NULL, value int); ②日付(date_created)のみ CREATE TABLE t1date (id int PRIMARY KEY, uuid VARCHAR(40) NOT NULL, date_created timestamp NOT NULL, value int); CREATE INDEX indexdate ON t1date (date_created); ③日付(date_created)+uuid CREATE TABLE t1dateuuid (id int PRIMARY KEY, uuid VARCHAR(40) NOT NULL, date_created timestamp NOT NULL, value int); CREATE INDEX indexdateuuid ON t1dateuuid (date_created, uuid); テスト用のテーブル(1/2) 16
④日付(date_created)+uuid+計測値(value) CREATE TABLE t1dateuuidval (id int PRIMARY KEY, uuid VARCHAR(40) NOT NULL, date_created timestamp NOT NULL, value int); CREATE INDEX indexdateuuidval ON t1dateuuidval (date_created, uuid, value); ⑤日付(date_created)+計測値(value) CREATE TABLE t1dateval (id int PRIMARY KEY, uuid VARCHAR(40) NOT NULL, date_created timestamp NOT NULL, value int); CREATE INDEX indexdateval ON t1dateval (date_created, uuid, value); ⑥uuid のみ CREATE TABLE t1uuid (id int PRIMARY KEY, uuid VARCHAR(40) NOT NULL, date_created timestamp NOT NULL, value int); CREATE INDEX indexuuid ON t1dateuuidval (uuid); テスト用のテーブル(2/2) 17
テストの結果(クエリ 5 回以上実行・最後の 3 回の平均) 19 INDEX の種類 MySQL 5.7 PostgreSQL 12 ①なし 2,000 ms 268 ms ②日時のみ 270 ms 26 ms ③日時+uuid 270 ms 29 ms ④日時+uuid+計測値 183 ms 30 ms ⑤日時+計測値 277 ms 29 ms ⑥uuid のみ 8,560 ms 269 ms
MySQL で「uuid のみ」が極端に遅いのは? ● uuid のみでは、ソートはできても絞り込みができない ● INDEX 全行スキャン→その後テーブル全行をフィルタ処理 ○ 集約時のソート効果 <<< アクセス経路が長くなるデメリット ○ 単純にフルテーブルスキャンするほうが速い 20 INDEX の種類 MySQL 5.7 PostgreSQL 12 ①なし 2,000 ms 268 ms ⑥uuid のみ 8,560 ms 269 ms
日時が先頭の INDEX(②③④⑤)の効果の違いは? ● MySQL は④でカバリング INDEX の効果あり ● PostgreSQL は④も効果なし 24 INDEX の種類 MySQL 5.7 PostgreSQL 12 ②日時のみ 270 ms 26 ms ③日時+uuid 270 ms 29 ms ④日時+uuid+計測値 183 ms 30 ms ⑤日時+計測値 277 ms 29 ms
mysql> EXPLAIN SELECT uuid, AVG(value) FROM t1date WHERE date_created BETWEEN '2020-10-01 00:00:00' AND '2020-11-30 23:59:59' GROUP BY uuid\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1date partitions: NULL type: range possible_keys: indexdate key: indexdate key_len: 4 ref: NULL rows: 282244 filtered: 100.00 Extra: Using index condition; Using temporary; Using filesort 1 row in set, 1 warning (0.00 sec) MySQL では、(②日時のみ) 25
mysql> EXPLAIN SELECT uuid, AVG(value) FROM t1dateuuid WHERE date_created BETWEEN '2020-10-01 00:00:00' AND '2020-11-30 23:59:59' GROUP BY uuid\G *************************** 1. row *************************** id: 1 select_type: SIMPLE table: t1dateuuid partitions: NULL type: range possible_keys: indexdateuuid key: indexdateuuid key_len: 4 ref: NULL rows: 294202 filtered: 100.00 Extra: Using index condition; Using temporary; Using filesort 1 row in set, 1 warning (0.00 sec) MySQL では、(③日時+uuid)※⑤日時+計測値もほぼ同じ 26
t1=> EXPLAIN SELECT uuid, AVG(value) FROM t1date WHERE date_created BETWEEN '2020-10-01 00:00:00' AND '2020-11-30 23:59:59' GROUP BY uuid; QUERY PLAN ------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------- Finalize GroupAggregate (cost=6014.99..6040.57 rows=100 width=69) Group Key: uuid -> Gather Merge (cost=6014.99..6038.32 rows=200 width=69) Workers Planned: 2 -> Sort (cost=5014.96..5015.21 rows=100 width=69) Sort Key: uuid -> Partial HashAggregate (cost=5010.64..5011.64 rows=100 width=69) Group Key: uuid -> Parallel Index Scan using indexdate on t1date (cost=0.43..4733.69 rows=55390 width=41) Index Cond: ((date_created >= '2020-10-01 00:00:00'::timestamp without time zone) AND (date_created <= '2020-11-30 23:59:59'::timestamp without time zone)) (10 rows) ※Parallel Index Scan PostgreSQL では、(②日時のみ) 29
t1=> EXPLAIN SELECT uuid, AVG(value) FROM t1dateuuid WHERE date_created BETWEEN '2020-10-01 00:00:00' AND '2020-11-30 23:59:59' GROUP BY uuid; QUERY PLAN ------------------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- Finalize GroupAggregate (cost=105685.08..105710.67 rows=100 width=69) Group Key: uuid -> Gather Merge (cost=105685.08..105708.42 rows=200 width=69) Workers Planned: 2 -> Sort (cost=104685.06..104685.31 rows=100 width=69) Sort Key: uuid -> Partial HashAggregate (cost=104680.74..104681.74 rows=100 width=69) Group Key: uuid -> Parallel Bitmap Heap Scan on t1dateuuid (cost=6545.33..104368.39 rows=62470 width=41) Recheck Cond: ((date_created >= '2020-10-01 00:00:00'::timestamp without time zone) AND (date_created <= '2020-11-30 23:59:59'::timestamp without time zone)) -> Bitmap Index Scan on indexdateuuid (cost=0.00..6507.85 rows=149929 width=0) Index Cond: ((date_created >= '2020-10-01 00:00:00'::timestamp without time zone) AND (date_created <= '2020-11-30 23:59:59'::timestamp without time zone)) (12 rows) PostgreSQL では、(③日時+uuid)※⑤もほぼ同じ 30
t1=> EXPLAIN SELECT uuid, AVG(value) FROM t1dateuuidval WHERE date_created BETWEEN '2020-10-01 00:00:00' AND '2020-11-30 23:59:59' GROUP BY uuid; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- ------------------- ------------------------------------------------- Finalize GroupAggregate (cost=106301.65..106327.24 rows=100 width=69) Group Key: uuid -> Gather Merge (cost=106301.65..106324.99 rows=200 width=69) Workers Planned: 2 -> Sort (cost=105301.63..105301.88 rows=100 width=69) Sort Key: uuid -> Partial HashAggregate (cost=105297.31..105298.31 rows=100 width=69) Group Key: uuid -> Parallel Bitmap Heap Scan on t1dateuuidval (cost=7065.83..104990.55 rows=61352 width=41) Recheck Cond: ((date_created >= '2020-10-01 00:00:00'::timestamp without time zone) AND (date_created <= '2020-11-30 23:59:59'::timestamp without time zone)) -> Bitmap Index Scan on indexdateuuidval (cost=0.00..7029.02 rows=147246 width=0) Index Cond: ((date_created >= '2020-10-01 00:00:00'::timestamp without time zone) AND (date_created <= '2020-11-30 23:59:59'::timestamp without time zone)) (12 rows) PostgreSQL では、(④日時+uuid+計測値) 31