16

コマンドライン PHP スクリプト (mysqlnd ドライバーで PDO を使用して準備されたクエリ) を介して MySQL クエリを実行しています。これは、左結合が 1 つの単純なクエリで、1 行あたり 100 行と 7 つの小さな列を返します。

このクエリを MySQL CLI で (問題の PHP スクリプトを実行している同じマシンで) 実行すると、SQL_NO_CACHE フラグがスローされていても、0.10 秒かかります。

このクエリを準備して PDO で実行すると、9 秒以上かかります。これは execute()のみです。フェッチ呼び出しにかかる時間は含まれません。

私のクエリの例:

SELECT HEX(al.uuid) hexUUID, al.created_on,
    IFNULL(al.state, 'ON') actionType, pp.publishers_id publisher_id,
    pp.products_id product_id, al.action_id, al.last_updated
FROM ActionAPI.actionLists al
LEFT JOIN ActionAPI.publishers_products pp
    ON al.publisher_product_id = pp.id
WHERE (al.test IS NULL OR al.test = 0)
    AND (al.created_on >= :since OR al.last_updated >= :since)
ORDER BY created_on ASC
LIMIT :skip, 100;

私が試したすべてのネイティブMySQLクライアントがほぼ瞬時に実行されたことを考えると、クエリに問題があるとは思いませんが、キックのEXPLAINは次のとおりです。

+----+-------------+-------+--------+-------------------------+------------+---------+-----------------------------------+------+-------------+
| id | select_type | table | type   | possible_keys           | key        | key_len | ref                               | rows | Extra       |
+----+-------------+-------+--------+-------------------------+------------+---------+-----------------------------------+------+-------------+
|  1 | SIMPLE      | al    | index  | created_on,last_updated | created_on | 8       | NULL                              |  100 | Using where |
|  1 | SIMPLE      | pp    | eq_ref | PRIMARY                 | PRIMARY    | 4       | ActionAPI.al.publisher_product_id |    1 |             |
+----+-------------+-------+--------+-------------------------+------------+---------+-----------------------------------+------+-------------+
2 rows in set (0.00 sec)

PDO が 8.9 秒かかっているのは一体何なのでしょうか?

編集:コメントで述べたように、これの mysql_query バージョンも作成しましたが、パフォーマンスは同じです。ただし、WHERE 句の一部を削除すると、MySQL クライアントと同じくらい高速に実行されます。気が遠くなるような詳細を読んでください。

4

4 に答える 4

7

この質問に関する非常に遅れた更新を提供します。

原因はわかりませんが、PHP と CLI では EXPLAIN が異なっていたことがわかりました。接続の何らかの側面により、MySQL がインデックスに別のフィールドを使用することを選択するようになるかどうかはわかりません。残念ながら、PHP の EXPLAIN は適切なインデックスが使用されていないことを示しましたが、CLI は使用されていました。

この (不可解な) ケースの解決策は、インデックス ヒンティングを使用することです。私の例からのこの変更されたクエリの「FROM」行を参照してください。

SELECT HEX(al.uuid) hexUUID, al.created_on,
    IFNULL(al.state, 'ON') actionType, pp.publishers_id publisher_id,
    pp.products_id product_id, al.action_id, al.last_updated
FROM ActionAPI.actionLists al USE INDEX (created_on)
LEFT JOIN ActionAPI.publishers_products pp
    ON al.publisher_product_id = pp.id
WHERE (al.test IS NULL OR al.test = 0)
    AND (al.created_on >= :since OR al.last_updated >= :since)
ORDER BY created_on ASC
LIMIT :skip, 100;

これが誰かを助けることを願っています!

于 2012-11-12T14:46:52.923 に答える
7

私も同じ問題を抱えていました。cli から起動した場合と PHP から起動した場合で、同じクエリの動作が異なっていました。正しいインデックスの使用法について述べたcliで説明します.PHPでは何もありませんでした。私が見つけたように、問題は型キャストでした。私の場合はdatetimeでした。比較値の型を具体的にキャストした後。where datetime_column > cast('2014-01-12 12:30:01' as datetime)すべてが機能します。

于 2014-01-24T17:31:11.893 に答える
1

PDO はリソースを使用して行の結果を操作します。これをインタープリター言語 (PHP) と比較すると、MySQL が結果を返すよりも処理に時間がかかるスクリプトが作成されます。

注: mysql_select_db() または mysqli_select_db() を使用すると、PDO よりもはるかに高速です。

より高速な PHP クエリの詳細については、次を参照してください: PHP: MySQL にクエリを実行する最速の方法は何ですか? PDO は非常に遅いため、

于 2012-09-09T04:23:34.013 に答える
0

コマンドラインで接続する場合、PHP で接続する場合とは異なる文字セットを使用する可能性が非常に高くなります。

インデックスを使用するように依頼すると、文字セットが問題を引き起こさないほど十分に近いため、それは行われます(推測では?テーブルと列の設定によって異なります)

そこにいくつかのユニコード文字を投げてみてください。おそらく悪い結果を返し始めます。

最良の結果を得るには、文字セットが接続、テーブル、および列で一致していることを確認してください。出来ないなら繋がりが一番大事

UTF-8 対 Latin1 mysql、インデックスは utf-8 では使用されません

もう少し情報があります

于 2014-01-24T17:38:58.370 に答える