2

最近、この質問があり、DreamHostのサーバーに送信するまですべてが正常に機能しました。

以下のクエリは実行に時間がかかりすぎるようで、一度に多くの行が処理される理由がわかりません。私のローカルサーバーでは、同じクエリが0.3秒で実行されました。

SELECT feed_entries . *
FROM feed_entries
WHERE 
id
IN (

SELECT e.id
FROM feed_entries AS e
INNER JOIN feeds AS f ON e.feed_id = f.id
INNER JOIN entries_categorias AS ec ON ec.entry_id = e.id
INNER JOIN categorias AS c ON ec.categoria_id = c.id
WHERE 
e.deleted =0
AND 
c.slug
IN ('entenda', 'google')
GROUP BY e.id
HAVING COUNT( DISTINCT ec.id ) =2

)
ORDER BY date DESC
LIMIT 1

これは私がサポートチームから受け取ったメッセージです:

このような他のクエリが原因でクエリがロックされ、650万レコードを11秒間処理しているようです。

# Query_time: 11.639269  Lock_time: 0.000192 Rows_sent: 2  Rows_examined:
6509098
use desenvolvimentistas;
SET timestamp=1280325753;
SELECT `e`.*, `f`.`titulo` AS `feedTitulo`, `f`.`url` AS `feedUrl` FROM
`feed_entries` AS `e`
 INNER JOIN `feeds` AS `f` ON e.feed_id =f.id WHERE (e.id IN (SELECT
`e`.`id` FROM `feed_entries` AS `e`
 INNER JOIN `feeds` AS `f` ON e.feed_id =f.id
 INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id
 INNER JOIN `categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted
=0) AND (e.id NOT IN ('', '', '842', '853', '774', '878')) AND
(e.imagem145x145 =1) AND (c.slug IN('destaque-2')) GROUP BY `e`.`id`
HAVING (COUNT(DISTINCT ec.id) =1))) ORDER BY `e`.`date` DESC LIMIT 4;

アイドル状態のローカルマシンでクエリを実行するのに0.3秒かかる可能性がありますが、一度に150のクエリを実行し、各サーバーが1,530万レコードを処理しているため、サーバーでは低速です。

私はmysql管理者にそれを見てもらいました、そして彼はそれが非常に非効率的であり、クエリがそれをとてもロックしていたのでデータベースにさえアクセス可能であることに驚いたと言いました。彼は、データベースがこのように続行され、サーバーの問題を引き起こす場合、データベースは無効になると述べました。彼は、調べた行を修正するか、MySQL PSを取得する必要があると述べましたが、mysql psはそれを修正せず、代わりにデータベースが無効になるのを防ぐだけです。

クエリは次のとおりです。

# Query_time: 25.944779  Lock_time: 0.000176 Rows_sent: 0  Rows_examined:
15378209
use desenvolvimentistas;
SELECT `feed_entries`.* FROM `feed_entries` WHERE (id IN (SELECT `e`.`id`
FROM `feed_entries` AS `e` INNER JOIN `feeds` AS `f` ON e.feed_id =f.id
INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id INNER JOIN
`categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted =0) AND
(c.slug IN('entenda','google')) GROUP BY `e`.`id` HAVING (COUNT(DISTINCT
ec.id) =2))) ORDER BY `date` DESC LIMIT 1;

修正が必要なもう1つは次のとおりです。

# Query_time: 27.010857  Lock_time: 0.000165 Rows_sent: 0  Rows_examined:
15382750
use desenvolvimentistas;
SET timestamp=1280325706;
SELECT `e`.*, `f`.`titulo` AS `feedTitulo`, `f`.`url` AS `feedUrl` FROM
`feed_entries` AS `e`
 INNER JOIN `feeds` AS `f` ON e.feed_id =f.id WHERE (e.id IN (SELECT
`e`.`id` FROM `feed_entries` AS `e`
 INNER JOIN `feeds` AS `f` ON e.feed_id =f.id
 INNER JOIN `entries_categorias` AS `ec` ON ec.entry_id =e.id
 INNER JOIN `categorias` AS `c` ON ec.categoria_id =c.id WHERE (e.deleted
=0) AND (c.slug IN('manchete', 'google')) GROUP BY `e`.`id` HAVING
(COUNT(DISTINCT ec.id) =2))) ORDER BY `e`.`date` DESC LIMIT 4;7:18
4

4 に答える 4

1

最初に確認するのは、ホストされているサーバーに正しいインデックスがあることです。時々、人々はデータベースを移行するときにこれらを移動するのを忘れます。

于 2010-07-28T15:34:43.527 に答える
1

あなたはいつでもそれをキャッシュすることができます;-)

于 2010-07-28T15:35:14.620 に答える
1

理想的には、質問ごとに1つのクエリを使用してください。質問の数に制限はなく、個々のクエリに関連するチャタリングを最小限に抑えます。

最初のクエリを次のように書き直しました。

  SELECT t.*
    FROM feed_entries t
   WHERE EXISTS(SELECT NULL
                  FROM feed_entries AS e
                  JOIN feeds AS f ON e.feed_id = f.id
                  JOIN entries_categorias AS ec ON ec.entry_id = e.id
                  JOIN categorias AS c ON ec.categoria_id = c.id
                 WHERE e.deleted = 0
                   AND c.slug IN ('entenda', 'google')
                   AND e.id = t.id
              GROUP BY e.id
                HAVING COUNT( DISTINCT ec.id ) = 2)
ORDER BY date DESC
   LIMIT 1

まだの場合は、JOIN基準で使用される列に少なくともインデックスを付けます。

クエリが150回実行されているというコメントを見ましたが、詳しく教えていただけますか?

于 2010-07-28T15:38:42.680 に答える
0

内側のクエリから単一のクエリを作成しようとします。次に、結果のIDを外側のonに手動で追加します(ここで、idは(1,2,3,4,5)にあります)。これによってパフォーマンスが自動的に向上するわけではありませんが、少なくとも何が起こっているかはわかっています。

彼らが問題を説明する方法では、外側のループからチェックされた単一のレコードごとに内側のループがテストされる場合もあります。これは、このアプローチによって修正されます。MySQLは十分に賢いと思いますが、これを単独で処理することはできません。

于 2010-07-28T15:37:58.357 に答える