7. 実行計画の読み方③ 下から順番に実行される。 COSTが大きい箇所は遅い原因の可能性が。 testdb=# explain select * from place_master p , member m testdb=# where p.pid = 5 and p.pid = m.pid order by m.id limit 10; QUERY PLAN ----------------------------------------------------------------------------------------- Limit (cost=517.11..517.13 rows=10 width=638) -> Sort (cost=517.11..517.74 rows=252 width=638) Sort Key: f.fid -> Nested Loop (cost=0.00..511.66 rows=252 width=638) -> Index Scan using place_master_pid on place_master p (cost=0.00..4.41 rows=1 width=599) Index Cond: (pid = 5) -> Index Scan using member_pid on member m (cost=0.00..504.73 rows=252 width=39) Index Cond: (m.pid = 5) ① ② ③ ④ ⑤
12. 遅いSQLの特定方法① 実行中のSQLを表示 SELECT pid, start, now() - start AS lap, current_query FROM (SELECT backendid, pg_stat_get_backend_pid(S.backendid) AS pid, pg_stat_get_backend_activity_start(S.backendid) AS start, pg_stat_get_backend_activity(S.backendid) AS current_query FROM (SELECT pg_stat_get_backend_idset() AS backendid) AS S ) AS S WHERE current_query <> '<IDLE>' ORDER BY lap DESC; pid | start | lap | current_query -------+------------------------+------------------+---------------------------------------- 16867 | 2008-12-24 16:49:54.00 | -00:00:02.000238 | SELECT * FROM master WHERE id = $1 AND valid = true LIMIT 1
22. ソート処理の削減 確認方法 実行計画中に不要なソートがないか確認する。 対策 可能であれば、 UNION の代わりに UNION ALL を使用する 不要な GROUP BY 、 ORDER BY を削除する GROUP BY + HAVING を使用する際は、 事前に WHERE 句で件数を絞る
25. SQLチューニング 都市伝説① IS NULL を使うとインデックスが使用されない NULL 値は Btree のインデックスでは格納されないため、 IS NULL 、 IS NOT NULL の検索の場合は、インデックスを使用できない。 8.3からインデックス使用可能に! testdb=# explain select count(id) from master where mail is null; QUERY PLAN ------------------------------------------------------------------------------------------ Aggregate (cost=4.90..4.91 rows=1 width=4) -> Index Scan using master_mail on master (cost=0.00..4.90 rows=1 width=4) Index Cond: (mail IS NULL)
26. SQLチューニング 都市伝説② IN句が使用可能なら、ORよりIN句を。 testdb=# explain select uid from master where id = '1' or uid = '5' or uid = '10'; QUERY PLAN ------------------------------------------------------------------------------------- Bitmap Heap Scan on master (cost=7.64..13.68 rows=3 width=4) Recheck Cond: ((id = 1) OR (id = 5) OR (id = 10)) -> BitmapOr (cost=7.64..7.64 rows=3 width=0) -> Bitmap Index Scan on master_pkey (cost=0.00..2.54 rows=1 width=0) Index Cond: (id = 1) -> Bitmap Index Scan on master_pkey (cost=0.00..2.54 rows=1 width=0) Index Cond: (id = 5) -> Bitmap Index Scan on master_pkey (cost=0.00..2.54 rows=1 width=0) Index Cond: (id = 10) testdb=# explain select uid from master where id in ('1' , '5' , '10'); QUERY PLAN ------------------------------------------------------------------------------- Bitmap Heap Scan on master (cost=7.06..13.09 rows=3 width=4) Recheck Cond: (uid = ANY ('{1,5,10}'::integer[])) -> Bitmap Index Scan on master_pkey (cost=0.00..7.06 rows=3 width=0) Index Cond: (id = ANY ('{1,5,10}'::integer[]))