Как можно оптимизировать этот запрос MySQL - PullRequest
0 голосов
/ 30 марта 2012

Учитывая следующую структуру таблицы

images                 data
 ------------------    ----------------------------------
| id    | filename |  | fromImageId | toImageId | result |
 ------------------    ----------------------------------

У меня есть следующее SELECT, чтобы получить все images.filename, которые не имеют записи в data (либо fromImageId, либо toImageId)

SELECT image.id, image.filename
FROM images image
WHERE NOT EXISTS(
    SELECT fromImageId, toImageId
    FROM data results
    WHERE fromImageId = image.id
        OR toImageId = image.id
) ORDER BY image.id

Поскольку таблица data довольно большая (500 000+), этот запрос занимает очень много времени для вычисления (около 10-15 секунд).

Я очень уверенздесь многое предстоит сделать для оптимизации, но я не могу понять, что можно сделать для оптимизации запроса.

PS: images.id - это PRIMARY KEY и оба fromImageId иtoImageId являются FOREIGN KEY с images.id

Ответы [ 4 ]

4 голосов
/ 30 марта 2012
SELECT
    images.id,
    filename
FROM
    images
LEFT JOIN `data` ON images.id = fromImageId
OR images.id = toImageId
WHERE
    fromImageId IS NULL AND toImageId IS NULL

И убедитесь, что индексы на fromImageId и toImageId.

2 голосов
/ 31 марта 2012

убедитесь, что ваша таблица «Данные» имеет, по крайней мере, два индекса ... Один только по идентификатору изображения FROM, другой по идентификатору To Image.Затем, немного отличаясь от того, что предлагал Майкл

select STRAIGHT_JOIN
      i.ID,
      i.FileName
   from
      Images i
         LEFT JOIN Data d1
            on i.ID = d1.FromImageID
         LEFT JOIN Data d2
            on i.ID = d2.ToImageID
   where
          d1.FromImageID is null
      AND d2.ToImageID is null

С двумя отдельными индексами этот запрос начинается с вашего файла изображения и связывается с ДВУМИ версиями вашей таблицы данных ... соответственно, к которой присоединяется EITHERили для изображения значений в то же время.Так что теперь, он должен просто пройти и выбросить только те записи, где ОБА таблицы «ДАННЫЕ» НЕ находят соответствия.

0 голосов
/ 30 марта 2012

Другой способ сформировать этот запрос:

SELECT image.id, image.filename
FROM images image
WHERE image.id NOT IN(
    SELECT fromImageId, toImageId
    FROM data results
) ORDER BY image.id

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

0 голосов
/ 30 марта 2012

NOT IN может быть лучшим выбором.Не проверял, но, пожалуйста, попробуйте следующее

SELECT image.id, image.filename
FROM images image
WHERE image.id NOT IN(
    SELECT IFNULL(fromImageId, toImageId)
    FROM data results
    WHERE fromImageId = image.id
        OR toImageId = image.id
) ORDER BY image.id
...