индексы в mysql SELECT AS или используя Views - PullRequest
0 голосов
/ 23 февраля 2009

У меня над головой большой запрос mysql (mysql 5.0), и я надеюсь, что кто-нибудь здесь может помочь.

Ранее я спрашивал, как получить различные значения из объединенного запроса счетчик mysql только для отдельных значений в объединенном запросе

Ответ, который я получил (с помощью подзапроса с объединением как)

select *
from media m
inner join
     ( select uid
     from users_tbl
     limit 0,30) map
  on map.uid = m.uid
inner join users_tbl u
  on u.uid = m.uid

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

мой запрос теперь выглядит так

SELECT mdate.bid, mdate.fid, mdate.date, mdate.time, mdate.title, mdate.name, 
       mdate.address, mdate.rank, mdate.city, mdate.state, mdate.lat, mdate.`long`,
       ext.link, 
       ext.source, ext.pre, meta, mdate.img
FROM ext
RIGHT OUTER JOIN (
  SELECT media.bid, 
         media.date, media.time, media.title, users.name, users.img, users.rank, media.address, 
         media.city, media.state, media.lat, media.`long`,
         GROUP_CONCAT(tags.tagname SEPARATOR ' | ') AS meta
  FROM media
  JOIN users ON media.bid = users.bid
  LEFT JOIN tags ON users.bid=tags.bid
  WHERE `long` BETWEEN -122.52224684058 AND -121.79760915942
    AND lat BETWEEN 37.07500915942 AND 37.79964684058
    AND date = '2009-02-23'
  GROUP BY media.bid, media.date
  ORDER BY media.date, users.rank DESC
  LIMIT 0, 30
) mdate ON (mdate.bid = ext.bid AND mdate.date = ext.date)

уф!

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

Какой лучший способ создать запрос, подобный этому, который позволит мне использовать индексы? Смею сказать, у меня на самом деле есть еще одна таблица, которую можно добавить в миксы позже.

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

Ответы [ 3 ]

1 голос
/ 23 февраля 2009

Во-первых, проверьте индексы на ext(bid, date), users(bid) и tags(bid), они действительно должны быть у вас.

Кажется, однако, что LONG и LAT вызывают у вас большинство проблем. Вы должны попытаться сохранить свои LONG и LAT как (coordinate POINT), создать SPATIAL INDEX для этого столбца и выполнить запрос, подобный этому:

WHERE MBRContains(@MySquare, coordinate)

Если по какой-то причине вы не можете изменить свою схему, вы можете попробовать создать дополнительные индексы, которые включают date в качестве первого поля:

CREATE INDEX ix_date_long ON media (date, `long`)
CREATE INDEX ix_date_lat ON media (date, lat)

Эти индексы будут более эффективными для вашего запроса, так как вы используете точный поиск на date в сочетании с поиском на расстоянии axes.

1 голос
/ 23 февраля 2009

Начиная заново:

Вопрос - почему вы группируете по media.bid и media.date? Может ли заявка иметь записи более чем на одну дату?

Вот более простая версия, чтобы попробовать:

SELECT 
    mdate.bid,
    mdate.fid,
    mdate.date,
    mdate.time,
    mdate.title,
    mdate.name, 
    mdate.address,
    mdate.rank,
    mdate.city,
    mdate.state,
    mdate.lat,
    mdate.`long`,
    ext.link, 
    ext.source,
    ext.pre, 
    meta,
    mdate.img,
    (   SELECT GROUP_CONCAT(tags.tagname SEPARATOR ' | ')
        FROM tags 
        WHERE ext.bid = tags.bid
        ORDER BY tags.bid GROUP BY tags.bid
    ) AS meta

FROM 
    ext

LEFT JOIN
    media ON ext.bid = media.bid AND ext.date = media.date

JOIN
    users ON ext.bid = users.bid

WHERE 
    `long` BETWEEN -122.52224684058 AND -121.79760915942
    AND lat BETWEEN 37.07500915942 AND 37.79964684058
    AND ext.date = '2009-02-23'
    AND users.userid IN
    (    
        SELECT userid FROM users ORDER BY rank DESC LIMIT 30
    )

ORDER BY 
    media.date, 
    users.rank DESC
    LIMIT 0, 30
0 голосов
/ 24 февраля 2009

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

создать таблицу создать таблицу # что угодно2

вставить в # что бы ни выбрали ... вставить в # what2 выберите ...

выберите из #whиновое присоединение #whwhat 2

....

Drop Table # независимо от того, выпадающий стол # что угодно2

Если в вашей системе достаточно памяти для хранения полных таблиц, это может сработать гораздо быстрее. Это зависит от размера вашей базы данных.

...