2016-12-05 5 views
0
これで

はJSフィドル:MySQLの - 別の属性で問い合わせるときにテーブルのソート効率的

http://sqlfiddle.com/#!9/4c7bc0/7

CREATE TABLE big_table(id INTEGER AUTO_INCREMENT PRIMARY KEY, 
         user_id INTEGER NOT NULL); 

SELECT * FROM big_table WHERE user_id IN (1, 100, 1000) 
ORDER BY id DESC LIMIT 10; 

として計画されている2番目のクエリ:どこ使用します。インデックスの使用。 filesortの使用

big_tableに数千万の行が含まれていると、ファイル・ポートがパフォーマンスを殺します。

私はどのように速く注文できますか?このクエリの

答えて

1

SELECT * 
FROM big_table 
WHERE user_id IN (1, 100, 1000) 
ORDER BY id DESC 
LIMIT 10; 

あなたは簡単に(1つの可能な方法があり、以下を参照)ORDER BYための作業を取り除くことはできません。最も重要なのは、あなたはbig_table(user_id)にインデックスを必要とする:

CREATE INDEX idx_bigtable_userid ON big_table(user_id); 

一致した行のわずか数十あるいは数百人がある場合、これは問題ないはずです。私はこのアプローチはIDに理由DESCで動作することを100%わからないことを言って開始する必要があります

CREATE INDEX idx_bigtable_userid ON big_table(user_id, id); 

別の可能性は、クエリを書き換えて、上のインデックスを使用することです。だから、あなたが行うことができます

SELECT * 
FROM big_table 
WHERE user_id = 1 
ORDER BY id DESC; 

:しかし、次のクエリは、インデックスを使用する必要があります

SELECT * 
FROM ((SELECT t.* 
     FROM big_table t 
     WHERE t.user_id = 1 
     ORDER BY id DESC 
     LIMIT 10 
    ) UNION ALL 
     (SELECT t.* 
     FROM big_table t 
     WHERE t.user_id = 100 
     ORDER BY id DESC 
     LIMIT 10 
    ) UNION ALL 
     (SELECT t.* 
     FROM big_table t 
     WHERE t.user_id = 1000 
     ORDER BY id DESC 
     LIMIT 10 
    ) 
    ) t 
ORDER BY id DESC 
LIMIT 10; 
+0

おそらくこの例のために動作しますが、実際の生活の中で、約1000のuser_id-sが来てそこにできることサブクエリ(または、私がそれを最適化しようとする前に元々結合していたもの) – jeje

+0

2つの推奨インデックスは同じです。テーブルは 'ENGINE = InnoDB'です。これは、InnoDBがPKカラムを各セカンダリインデックスに追加するためです。 –

+0

'IN'に複数の' user_id'がある場合、インデックスは_cannot_を使用してソートを避けることができます。これは、インデックスエントリが 'id'の順序にないためです。しかし、 'ORDER BY user_id、id DESC'はソートを避けると思います。 –

関連する問題