Помогите оптимизировать запрос с UNION

-Dima-

Гуру форума
Регистрация
3 Окт 2009
Сообщения
167
Реакции
66
Собственно есть такой запрос:

Код:
(SELECT * FROM `table1` WHERE id IN ( 736,14419,4170,14116 ))
UNION
(SELECT * FROM `table2` WHERE id IN ( 2995,3480,5981,5282 ))
UNION
(SELECT * FROM `table3` WHERE id IN ( 4610,13668,9654 ))
UNION
(SELECT * FROM `table4` WHERE id IN ( 5292 ))
ORDER BY `column4` ASC

по полям id стоит индекс.
Мне нужно из таблиц брать произвольные строки
Голова уже пухнет:hi:

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

вообще-то такое ощущение что у вас таблицах table1..table4 одни и те же колонки на '99%' - в таком случае оптимизировать, вполне возможно, надо не запрос а организацию и логику БД
 
Да, под "оптимизировать" я имел ввиду и быстродействие и текст запроса, ну или хоть что-то одно :)

Ощущение у вас верное.
в таком случае оптимизировать, вполне возможно, надо не запрос а организацию и логику БД
Может вы и правы, я тоже об этом думал.
Но мне кажется, если их объеденить, тогда будет сложнее делать выборку рандомных значений с учетом параметров...
Ну вот к примеру, допустим мне нужно выбрать рандомных 5 картинок синего цвета, 3 картинки пурпурного и 4 картинки бирюзового.
картинок синего цвета -15к шт
пурпурного - 9к шт
бирюзового - 13к шт
(пример вымышлен).
Может как-то лучше можно организовать, но мне как разбить на разные таблицы, что-то ничего на ум не пришло...
 
Согласно многим тестам, решение с UNION и заранее указанными id в условии IN -- самое производительное на MySQL, при условии, что проставлены необходимые индексы.

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

Можно тут почитать затяжные дискуссии на эту тему: Для просмотра ссылки Войди или Зарегистрируйся
 
Угу, спасибо, листал вчера ))
Но так и не пришел к оптимальному решению...
Да, если происходят частые удаления, тут действительно напряг будет, тут мне понравилась идея с триггерами.
Но благо у меня в данном случае нет частых обновлений.
Кстати, вот тоже интересные 2 дискуссии:
Для просмотра ссылки Войди или Зарегистрируйся
Для просмотра ссылки Войди или Зарегистрируйся

Просто думал, что может кто уже нашел для себя оптимальный вариант, для такой задачи...:rolleyes:
Не знаю вот, как с процедурами будет дело обстоять, еще не пробовал.
Но что-то мне кажется, что остановлюсь на первоначальном варианте...))
 
Решение с юнионом довольно шустрое само по себе, если есть индекс по id - там работы-то по индексу пройтись и выдернуть нужную строку, так что тут оптимизировать просто нечего, модификации пойдут только во вред. А вот с удалением все интереснее - можно нагородить огород с еще одной табличкой-очередью и двумя триггерами, срабатыающими по delete и insert, но что-то мне подсказывает, что если размер дыры не столь заметен, активных delete не планируется, а выборки рандомные, то проще либо заведомо делать выборку на 1-2 элемента больше и потом из массива просто выбирать нужное количество, либо сверять количество запрошенных строк к реально выбранным и потом просто сделать довыборку, если IN попал на дыру.
 
Собственно есть такой запрос:

Код:
(SELECT * FROM `table1` WHERE id IN ( 736,14419,4170,14116 ))
UNION
(SELECT * FROM `table2` WHERE id IN ( 2995,3480,5981,5282 ))
UNION
(SELECT * FROM `table3` WHERE id IN ( 4610,13668,9654 ))
UNION
(SELECT * FROM `table4` WHERE id IN ( 5292 ))
ORDER BY `column4` ASC

по полям id стоит индекс.
Мне нужно из таблиц брать произвольные строки
Голова уже пухнет:hi:

Можно ли как-то оптимизировать такой запрос??
Т.к. в данном примере таких таблиц всего 4, а если их будет на порядок больше...

Для начала я бы посоветовал убрать "*" и union зфменить на union all.
union объединяет и группирует наборы данных.
Если ИД во всех ин-ах разные то это решение вам подойдет.

Покажите полный текст запроса....
 
К сожалению с MySQL работал мало. Но если брать MS SQL к вышесказанному, вместо чисел лучше в запросе что-бы была переменная, иначе постоянно перед выполнением перестраивается план.
А вообще действительно интересно увидеть весь запрос.
А во вторых, что содержится в этих таблицах, может быть была возможность использовать 1 таблицу под эту задачу вместо 4?
 
Для начала я бы посоветовал убрать "*" и union заменить на union all.
union объединяет и группирует наборы данных.
Если ИД во всех ин-ах разные то это решение вам подойдет.

Покажите полный текст запроса....

по поводу * не уверен, что это много даст, если я перечислю все столбцы вместо этого..

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

За union all, спасибо. Вылетело из головы..
Одинаковых строк то нету, точно)
 
Назад
Сверху