Как я могу улучшить производительность этого запроса? - PullRequest
2 голосов
/ 28 июля 2010

Недавно у меня был вопрос , и все работало правильно, пока я не отправил его на свой сервер в 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

Это сообщение, которое я получил от службы поддержки:

Ну, похоже, что запрос заблокирован из-за этих других запросов как этот, обработка 6,5 миллионов записи, за 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 в время, и каждый обрабатывает 15,3 миллиона записей.

Наш администратор 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;

Вот еще одно, что нужно исправить:

# 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 ]

1 голос
/ 28 июля 2010

В идеале, пожалуйста, один запрос на вопрос - количество вопросов, которые вы можете задать, не ограничено, и это сводит к минимуму болтовню, связанную с каждым отдельным запросом.

Я переписал ваш первый запрос как:

  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 раз - не могли бы вы уточнить?

1 голос
/ 28 июля 2010

вы всегда можете его кешировать; -)

1 голос
/ 28 июля 2010

Ну, первое, что я хотел бы проверить, это то, что у вас есть правильные индексы на размещенном сервере. Иногда люди забывают переместить их при переносе баз данных.

0 голосов
/ 28 июля 2010

Я бы попытался создать один запрос из внутреннего.Затем добавьте полученные идентификаторы вручную во внешнее включение (где id в (1,2,3,4,5)).Хотя это автоматически не повышает производительность, вы, по крайней мере, знаете, что происходит.

То, как они описывают проблему, может даже быть, что внутренний цикл проверяется для каждой отдельной записи, проверенной из внешнего цикла,будет исправлено этим подходом.Хотя я предполагаю, что MySQL будет достаточно умным, но не справится с этим сам по себе.

...