sql >> データベース >  >> RDS >> Mysql

Mysqlサブクエリは常にファイルソートを実行します

    Using filesort 必ずしも悪いことではありません。名前は少し誤解を招くです。 「ファイル」が含まれていますが、データがハードディスクのどこかに書き込まれているという意味ではありません。まだメモリ内で処理されています。

    マニュアル から :

    クエリでこれが発生する理由を理解していますか?この種のサブクエリを使用することは、依存であるため、悪いスタイルです。 サブクエリ。 appのすべての行 サブクエリが実行されるテーブル。ひどい。 joinを使用してクエリを書き直します 。

    select app.id,
    gp.dateup
    from app 
    join gamesplatform_pricehistory gp on gp.id_app = app.id
    where app.id > 0
    and gp.country = 1
    and gp.dateup = (SELECT MAX(dateup) FROM gamesplatform_pricehistory smgp WHERE smgp.id_app = gp.id_app AND smgp.country = 1)
    ;
    

    これは引き続き依存サブクエリを使用しますが、explain はるかに良く見えます:

    | id |        select_type | table |  type | possible_keys |     key | key_len |                        ref | rows |                    Extra |
    |----|--------------------|-------|-------|---------------|---------|---------|----------------------------|------|--------------------------|
    |  1 |            PRIMARY |   app | index |       PRIMARY | PRIMARY |       4 |                     (null) |    2 | Using where; Using index |
    |  1 |            PRIMARY |    gp |   ref |        id_app |  id_app |       5 |    db_2_034bc.app.id,const |    1 | Using where; Using index |
    |  2 | DEPENDENT SUBQUERY |  smgp |   ref |        id_app |  id_app |       5 | db_2_034bc.gp.id_app,const |    1 |              Using index |
    

    それを書き直す別の方法は、これです:

    select app.id,
    gp.dateup
    from app 
    LEFT join 
    (SELECT id_app, MAX(dateup) AS dateup 
     FROM gamesplatform_pricehistory
     WHERE country = 1
     GROUP BY id_app
    )gp on gp.id_app = app.id
    where app.id > 0
    ;
    

    説明はさらに良く見えます:

    | id | select_type |                      table |  type | possible_keys |     key | key_len |    ref | rows |                    Extra |
    |----|-------------|----------------------------|-------|---------------|---------|---------|--------|------|--------------------------|
    |  1 |     PRIMARY |                        app | index |       PRIMARY | PRIMARY |       4 | (null) |    2 | Using where; Using index |
    |  1 |     PRIMARY |                 <derived2> |   ALL |        (null) |  (null) |  (null) | (null) |    2 |                          |
    |  2 |     DERIVED | gamesplatform_pricehistory | index |        (null) |  id_app |      13 | (null) |    2 | Using where; Using index |
    

    そして、これが依存サブクエリをまったく持たないバージョンです:

    select app.id,
    gp.dateup
    from app 
    left join gamesplatform_pricehistory gp on gp.id_app = app.id and country = 1
    left join gamesplatform_pricehistory gp2 on gp.id_app = app.id and country = 1 and gp.dateup < gp2.dateup
    where app.id > 0
    and gp2.dateup is null
    ;
    

    これは次のように機能します:gp.dateupの場合 最大で、gp2.dateupはありません 。



    1. ノードJsmysql(およびmysql2)ECONNRESET

    2. PHPスクリプトの日時

    3. 2つの異なるEC2インスタンスでのDjangoとPostgreSQLのセットアップ

    4. RESTfulApiまたはSocket.IO