2009-02-23 3 views
0

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

Ранее я спросил, как получить различные значения из объединенного запроса mysql count only for distinct values in joined query

Ответ я погорячился (с использованием подзапроса с присоединиться в качестве)

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

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

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

+0

Просмотрев рекомендацию Квасной по использованию SPACIAL INDEX, я понял, что это была ошибка в индексе, который у меня был, и время отклика значительно снизилось (теперь 0,1 секунды). Однако, EXPLAIN все еще указывает, что я делаю запрос неиндексированных столбцов. – pedalpete

ответ

1

Начиная свежие:

Вопрос - почему вы группирование по обе 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

Ну, я не группирую ни на что, я просто отформатировал запрос так, чтобы он был читабельным. – Quassnoi

+0

спасибо le dorfier, у меня теперь все хорошо работает, но когда я пройду свой текущий срок, я попробую переписывая запрос по-своему и посмотрим, смогу ли я это сделать. Это выглядит проще. – pedalpete

1

Сначала проверьте для индексов на ext(bid, date), users(bid) и tags(bid), вы должны действительно иметь их.

Кажется, что это LONG и LAT, которые вызывают большинство проблем. Вы должны стараться держать вашу LONG и LAT как (coordinatePOINT), создать 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.

+0

Хотя я не отрицаю преимуществ SPATIAL INDEX, по какой-то причине я не смог создать его в своей базе данных (возможно, потому, что я храню lat & long seperately. процесс я понял, что у меня была ошибка в моем индексе latlong. Время запроса составляет 0,1 с. – pedalpete

+0

Если вы хотите ПРОСТРАНСТВЕННЫЙ, вы должны сохранить ваши координаты как особый тип, GEOMETRY (POINT, в вашем случае). И тот факт, что LAT/LONG указатель помог вам сказать, что вы действительно хотите ПРОСТРАНСТВЕННЫЙ :) – Quassnoi

+0

См. Обновленное сообщение для ссылок на типы GEOMETRY. – Quassnoi

0

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

создать таблицу #whatever создать таблицу # whatever2

вставки в #whatever выберите ... вставки в # whatever2 выбрать ...

выбрать из #whatever присоединиться #whatever 2

....

стол падение #whatever падение стол # whatever2

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