2

PHPアプリケーションの一部として次のクエリに遭遇しました。クエリはmysql5.0では高速(1秒未満)で実行されますが、mysql5.1以降では完了するまでに約7分かかります。

返される結果はわずか3行ですが、このクエリを実行している5.1サーバーでmysqldプロセスを実行すると、テーブルから数分間straceデータを継続的に読み取っていることがわかります(200バイトで7000行しかないテーブル)Event行ごと)-おそらくそれを複数回再読み取りします。

だから問題は、私が遭遇しているここで何が違うのか、そしてこれが5.0で実行されるのと同じくらい速く5.1で実行されるように物事(クエリまたはより良いがいくつかのMySQL設定)を変更するにはどうすればよいですか?


参照データ

非難するクエリ

SELECT S.Sections_ID, S.Sections_Name, S.Sections_CustomURL
FROM Sections S
WHERE S.Sections_Status = 'Active'
    AND S.Sections_Name!='Hidden'
    AND S.Sections_ParentID = 0
    AND S.Sections_MainSection = 1
    AND (
        SELECT COUNT(MainEvent.Event_ID) AS tot
        FROM Event MainEvent, Event_Section ES
        WHERE ES.EventSection_EventID=MainEvent.Event_ID
            AND ES.EventSection_SectionID=S.Sections_ID
            AND (
                (MainEvent.Event_DateTime > '2011-12-27 18:05:00')
                OR
                    (
                        (
                        SELECT ChildEvent.Event_DateTime
                        FROM Event ChildEvent
                        WHERE ChildEvent.Event_ParentEventID=MainEvent.Event_ID
                        ORDER BY ChildEvent.Event_DateTime DESC LIMIT 1
                        ) > '2011-12-27 18:05:00'
                    )
                )
            AND (MainEvent.Event_ParentEventID=0 or MainEvent.Event_ParentEventID IS NULL) 
            AND (MainEvent.Event_Status='Active' or MainEvent.Event_Status='Canceled') 
            AND MainEvent.Event_ID IN (
                SELECT
                Event_Website.EventWebsite_EventID
                FROM Event_Website 
                WHERE Event_Website.EventWebsite_CompanyID='3'
            )
        )>0
ORDER BY S.Sections_Order ASC, S.Sections_Name ASC

参照されるテーブルには、次の行数があります

セクション:60
イベント:7000
Event_Section:7000
Event_Website:15000

以下はEXPLAIN、5.0(高速)および5.1(低速)サーバーからの上記のクエリの場合です。
スペースのためにクリップされています。うまくいけば、私は有用なものを何も切り出さなかった。

遅い(5.1)

+----+---------------+-------------+----------------------------+------------------------+---------+----------------------------------+------+-----------------------------+
| id | table         | type        | possible_keys              | key                    | key_len | ref                              | rows | Extra                       |
+----+---------------+-------------+----------------------------+------------------------+---------+----------------------------------+------+-----------------------------+
|  1 | S             | ref         | Sections_ParentID          | Sections_ParentID      | 5       | const                            |   10 | Using where; Using filesort |
|  2 | MainEvent     | ref_or_null | PRIMARY,Event_DateTime,... | Event_ParentID         | 5       | const                            | 4582 | Using where                 |
|  2 | ES            | ref         | EventSection_EventID       | EventSection_EventID   | 10      | MainEvent.Event_ID,S.Sections_ID |    1 | Using where; Using index    |
|  4 | Event_Website | ref         | EventWebsite_CompanyID     | EventWebsite_CompanyID | 4       | const                            | 4421 | Using where                 |
|  3 | ChildEvent    | index       | Event_ParentID             | Event_DateTime         | 8       | NULL                             |    1 | Using where                 |
+----+---------------+-------------+----------------------------+------------------------+---------+----------------------------------+------+-----------------------------+

速い(5.0)

+----+---------------+--------+---------------------------+------------------------+---------+-------------------------+------+-----------------------------+
| id | table         | type   | possible_keys             | key                    | key_len | ref                     | rows | Extra                       |
+----+---------------+--------+---------------------------+------------------------+---------+-------------------------+------+-----------------------------+
|  1 | S             | ref    | Sections_ParentID         | Sections_ParentID      | 5       | const                   |   10 | Using where; Using filesort | 
|  2 | ES            | index  | EventSection_EventID      | EventSection_EventID   | 10      | NULL                    | 5610 | Using where; Using index    | 
|  2 | MainEvent     | eq_ref | PRIMARY,Event_DateTime,...| PRIMARY                | 4       | ES.EventSection_EventID |    1 | Using where                 | 
|  4 | Event_Website | ref    | EventWebsite_CompanyID    | EventWebsite_CompanyID | 4       | const                   | 5809 | Using where                 | 
|  3 | ChildEvent    | ref    | Event_ParentID            | Event_ParentID         | 5       | MainEvent.Event_ID      |    4 | Using where; Using filesort | 
+----+---------------+--------+---------------------------+------------------------+---------+-------------------------+------+-----------------------------+
4

3 に答える 3

2

書き直すための2つの提案:

  1. クエリに変更IN (SELECT ...)JOINます。

  2. に変更 (SELECT COUNT(MainEvent.Event_ID) ...) > 0EXISTS (SELECT * ...)ます。

于 2011-12-28T17:34:40.957 に答える
1

Mysqlバージョン5.0および5.1(およびすべての下位バージョン)は、この方法で(依存する)サブクエリを操作するときに使用するのに最適なバージョンではありません。

これらのバージョンで立ち往生している場合は、結合へのクエリを書き直してみてください。また使用

"{columnname} IN(SELECT .... FROM {tablename} WHERE ....)"

多くの場合、パフォーマンスキラーです。多くの場合、2つのクエリに分割する方が、その構文を使用するよりも高速です。

最初のクエリを実行し、必要なすべてのIDを取得してから、これらのIDを上記のクエリに配置します

"{columnname} IN(12、345、356、653など...)"

MariaDBはこれを部分的に解決しており、MySQLの完全な代替品です。機密データがない場合は、データベースダンプを送っていただけませんか。MariaDBで上記のクエリのベンチマークを行います。

于 2011-12-28T09:34:28.393 に答える
1

クエリを書き直しました。現在はJOINSを使用しています。dbスキーマをアタッチしていないため、このクエリをテストできませんでした。質問に添付してください。

SELECT S.Sections_ID, S.Sections_Name, S.Sections_CustomURL
FROM Sections AS S
JOIN Event_Section AS ES ON ES.EventSection_SectionID = S.Sections_ID
JOIN Event AS MainEvent ON ES.EventSection_EventID = MainEvent.Event_ID
JOIN Event_Website ON Event_Website.EventWebsite_EventID = MainEvent.Event_ID
LEFT JOIN Event AS ChildEvent ON ChildEvent.Event_ParentEventID = MainEvent.Event_ID
WHERE S.Sections_Status = 'Active'
    AND S.Sections_Name != 'Hidden'
    AND S.Sections_ParentID = 0
    AND S.Sections_MainSection = 1
    AND (MainEvent.Event_ParentEventID = 0 OR MainEvent.Event_ParentEventID IS NULL)
    AND (MainEvent.Event_DateTime > '2011-12-27 18:05:00' OR ChildEvent.Event_DateTime > '2011-12-27 18:05:00')
    AND (MainEvent.Event_Status='Active' OR MainEvent.Event_Status='Canceled')
    AND Event_Website.EventWebsite_CompanyID = '3'
GROUP BY S.Sections_ID
ORDER BY S.Sections_Order ASC, S.Sections_Name ASC
于 2011-12-28T18:54:08.410 に答える