Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
99
Help us understand the problem. What is going on with this article?
@wcareer

SQLの効率化

More than 5 years have passed since last update.

SQLを高速化について、少し勉強したのでメモを残しておきます。

サブクエリを引数に取る時はINよりEXISTSまたは結合


SELECT * FROM A WHERE id IN(SELECT id FROM B);
-- より
SELECT * FROM A AA WHERE EXISTS(SELECT B BB WHERE AA.id = BB.id);
-- の方が早い。もしくは
SELECT AA.id, AA.name FROM A INNER JOIN B BB ON AA.id = BB.id;
  • EXISTSは条件に合致するものを1行でも見つけたらそこで検索終了
  • INは全表検索してしまう
  • 結合キーにインデックスが張られていればインデックス参照だけで済む

※PostgreSQLは7.4からIN述語にサブクエリが速度改善されている
※OracleはINを使ってもインデックススキャンを行う様に工夫されている

DISTINCTをEXISTSで


SELECT AA.name FROM A AA INNNER JOIN B BB ON AA.name = BB.name;
-- より
SELECT name FROM A AA WHERE EXISTS(SELECT * FROM B BB WHERE AA.name = BB.name); 
  • DISTINCTは重複を排除するソート
  • 上記であればソートが発生しない

ALLオプション


SELECT * FROM A
UNION
SELECT * FROM B
-- より
SELECT * FROM A
UNION ALL
SELECT * FROM B
  • UNIONは重複排除のソートを行う
  • ALLを使えばソートは発生しない

GROUP BY と ORDER BY でインデックスを使う

  • インデックスの存在するキーを指定すればソート時に高速化できる
  • ユニークインデックスの場合はソートをスキップできる

MAXまたMINでインデックスを使う

  • 引数にインデックスが存在した場合、そのインデックスだけで済む

-- IN述語で複数のキーを使う場合はまとめる
SELECT id,name,email FROM A AA 
WHERE name IN (SELECT name FROM B BB WHERE AA.id = BB.id) 
AND email IN (SELECT email FROM B BB WHERE AA.id = BB.id);
-- より
SELECT * FROM A AA
WHERE id || name || email IN (SELECT id || name || email FROM B BB)
-- の方が検索が1度で良い。または
SELECT * FROM A AA
WHERE (id,name,email) IN (SELECT id,name,email FROM B BB);
-- インデックスを利用できる

インデックスをうまく活用する

  • 検索条件の右側で式を使えばインデックスを使用できる
    
    -- test_1列にインデックスが張られているとして
    SELECT * FROM A WHERE test_1 > 108 / 1.08 
    
  • IS NULL・IS NOT NULL 述語を使わない
    
    -- IS NULL または IS NOT NULL はインデックスを利用できない
    SELECT * FROM A WHERE test_1 IS NOT NULL;
    
  • 否定型は使わない
    
    <>、 !=、 NOT INなどは全表検索し、インデックスを使用しない
    
  • 前方一致を使う
    
    SELECT * FROM A WHERE test_1 LIKE 'z%';
    

ちなみにインデックスとは
以下参照元:http://www.techscore.com/tech/sql/15_01.html/#sql151


引用:インデックスとは、データの検索速度を向上させるために、どの行がどこにあるかを示した索引のことです。

つまり、目次ですね。本などで調べる時はやはり目次を見た方が早いですよね。

作り方は


-- postgreSQL
CREATE [UNIQUE] INDEX インデックス名 ON テーブル名(列名,...) ;
-- oracle
CREATE [UNIQUE] INDEX インデックス名 ON テーブル名(列名 [ ASC | DESC ],...) ;

消し方

DROP INDEX インデックス名 ;

SQLの勉強することによりアプリケーションの速度向上も望めると思います。
今後はこの情報をAppにも活用していきたいですね。

99
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
wcareer
技術的メモに使っています。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
99
Help us understand the problem. What is going on with this article?