MySQL Beach Ball из НЕ В запросе - PullRequest
0 голосов
/ 29 ноября 2009

У меня есть два запроса, каждый из которых возвращает список идентификаторов узлов

SELECT node.nid 
  FROM dpf_node AS node 
 WHERE node.type = 'image' AND node.nid; 

SELECT node.nid 
  FROM dpf_node AS node, dpf_image_galleries_images AS image 
 WHERE image.image_nid = node.nid  
   AND node.type = 'image'
   AND image.gallery_nid = 138;

Оба они работают правильно

В конечном счете, хотя я хочу получить список идентификаторов узлов, которые находятся в первом списке результатов, а не во втором, я использовал этот запрос:

SELECT node.nid 
  FROM dpf_node AS node 
 WHERE node.type = 'image' 
   AND node.nid NOT IN (SELECT node.nid 
                          FROM dpf_node AS node, dpf_image_galleries_images AS image 
                         WHERE image.image_nid = node.nid 
                           AND node.type = 'image' 
                           AND image.gallery_nid = 138);

Какое-то время это работало нормально, но только сегодня вечером это был профессионал, играющий в пляжный мяч и заставляющий апача зависать. Я подозреваю (/ надеюсь), что очистка данных и повторный запуск решат их, но очень хотят исправить реальную проблему на тот случай, если она возродится, как только система заработает.

Ответы [ 3 ]

1 голос
/ 29 ноября 2009

MySQL может делать довольно глупые вещи с коррелированными подзапросами (посмотрите на план запросов). Если вам просто нужны вещи из первого запроса, которых нет во втором, вы можете получить значительно лучшую производительность из LEFT OUTER JOIN из двух, с условием фильтрации, отфильтровывающим строки, имеющие нулевые значения для второго набора результатов. 1001 *

1 голос
/ 29 ноября 2009

Измените его на запрос NOT EXISTS, чтобы повысить производительность:

SELECT node.nid 
  FROM dpf_node AS node 
 WHERE node.type = 'image'
       AND NOT EXISTS (
         SELECT 1
         FROM dpf_node AS i_node
         JOIN dpf_image_galleries_images AS image ON i_node.nid = image.image_nod
         WHERE node.type = 'image'
         AND image.gallery_nid = 138
         AND i_node.nid = node.nid
       )

Вы также должны убедиться, что у вас есть адекватные индексы.

0 голосов
/ 29 ноября 2009

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

SELECT node.nid
FROM dpf_node AS node
JOIN dpf_image_galleries_images AS image 
    ON node.nid = image.image_nod
WHERE node.type = 'image'
AND image.gallery_nid != 138

В зависимости от того, как выложены ваши данные и сколько их там, это должно работать намного лучше, чем подзапрос предложения where. И это намного легче понять.

...