Задавайте вопросы, мы ответим
Вы не зашли.
Здравствуйте.
Есть проблема с выборкой данных, надеюсь, на вашу помощь.
Имеются две таблицы: одна содержит альбомы, вторая - исполнителей. Необходимо сделать выборку связав две таблицы альбом+исполнитель. Нет проблем, пока не начинаю сортировать по названию исполнителя (без этого - никак), но при этом время выполнения запроса стремиться к бесконечности.
Обе таблицы содержат более 2ух миллионов записей, LIMIT использую.
Неактивен
Ну, во-первых, Вам нужен ключик на music_albums(singer_id), раз уж он участвует в объединении.
Во-вторых, наверняка запрос более длинный
Неактивен
Спасибо за ответ.
Конечно в итоге запрос еще больше будет - сейчас хочется его заставить работать хотя бы с одним объединением.
paulus написал:
Вам нужен ключик на music_albums(singer_id), раз уж он участвует в объединении.
Не могли бы вы объяснить какой ключ имеется в виду?
Неактивен
Проблема, судя по всему, в размере временной таблицы - результате объединения. Когда попробовал создавать временные таблицы в оперативной памяти
Неактивен
Я имею в виду ключик, получающийся командой
ALTER TABLE music_albums ADD INDEX(singer_id)
Неактивен
Попробуйте для начала так:
Отредактированно Magz (14.05.2009 15:54:51)
Неактивен
Это все равно даст FTS, правда ведь? ключика то нет.
Неактивен
paulus, к сожалению легче не стало. Запрос все равно выполняется долго (убил его через 5 минут).
Magz, да я тоже думал о подобном. Но можно ли тогда будет указывать дополнительные условия, например `rating` > 0 ? Или придется делать либо то, либо то?
Кстати, ошибку синтекса на ваш запрос выдает.
Неактивен
А explain?
Неактивен
paulus написал:
А explain?
Без изменений.
Неактивен
paulus написал:
Это все равно даст FTS, правда ведь? ключика то нет.
Чистая правда! Без ключика будет гораздо хуже, чем с ним. Просто я думаю, что backflip уже последовал Вашему совету, поэтому ничего про ключик не сказал.
backflip написал:
Magz, да я тоже думал о подобном. Но можно ли тогда будет указывать дополнительные условия, например `rating` > 0 ? Или придется делать либо то, либо то? Кстати, ошибку синтекса на ваш запрос выдает.
Если стоит задача "Выбрать исполнителей в алфавитном порядке рейтинг альбомов которых не равен нулю", то "в лоб" не пройдет. Нужно будет идти от обратного - сначала выбрать все альбомы с ненулевым рейтингом, а потом их свзяывать с исполнителями. Основная идея - это сократить количество строк после объединения. Ибо никакие индексы не помогут, когда нужно отсортировать 4 ГБ данных!
Какая конкретно ошибка синаксиса вылезает?
Неактивен
В принципе понял, что либо то либо то В крайнем случае оставлю пользователей без сортировки и заменю ее фильтрами.
Magz написал:
Какая конкретно ошибка синаксиса вылезает?
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '`music_singer_names` ORDER BY `singer_name_en` LIMIT 0 , 50 ) msn ON ( `msn` . `' at line 1
Отредактированно backflip (15.05.2009 12:45:13)
Неактивен
Рррр, пришлось создать таблички
[aquatica] root test > explain SELECT * FROM `music_albums` LEFT JOIN `music_singer_names` ON (`music_singer_names`.`id`=`music_albums`.`singer_id`) ORDER BY `singer_name_en` LIMIT 0,50; +----+-------------+--------------------+--------+---------------+---------+---------+-----------------------------+-------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------------------+--------+---------------+---------+---------+-----------------------------+-------+---------------------------------+ | 1 | SIMPLE | music_albums | ALL | NULL | NULL | NULL | NULL | 32768 | Using temporary; Using filesort | | 1 | SIMPLE | music_singer_names | eq_ref | PRIMARY | PRIMARY | 4 | test.music_albums.singer_id | 1 | | +----+-------------+--------------------+--------+---------------+---------+---------+-----------------------------+-------+---------------------------------+ 2 rows in set (0,00 sec) [aquatica] root test > alter table music_albums add index (singer_id); Query OK, 32768 rows affected (0,15 sec) Records: 32768 Duplicates: 0 Warnings: 0 [aquatica] root test > explain SELECT * FROM `music_albums` LEFT JOIN `music_singer_names` ON (`music_singer_names`.`id`=`music_albums`.`singer_id`) ORDER BY `singer_name_en` LIMIT 0,50; +----+-------------+--------------------+--------+---------------+---------+---------+-----------------------------+-------+---------------------------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------------------+--------+---------------+---------+---------+-----------------------------+-------+---------------------------------+ | 1 | SIMPLE | music_albums | ALL | NULL | NULL | NULL | NULL | 32768 | Using temporary; Using filesort | | 1 | SIMPLE | music_singer_names | eq_ref | PRIMARY | PRIMARY | 4 | test.music_albums.singer_id | 1 | | +----+-------------+--------------------+--------+---------------+---------+---------+-----------------------------+-------+---------------------------------+ 2 rows in set (0,00 sec) [aquatica] root test > explain SELECT * FROM `music_albums` JOIN `music_singer_names` ON (`music_singer_names`.`id`=`music_albums`.`singer_id`) ORDER BY `singer_name_en` LIMIT 0,50; +----+-------------+--------------------+-------+---------------+----------------+---------+----------------------------+------+-------------+ | id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra | +----+-------------+--------------------+-------+---------------+----------------+---------+----------------------------+------+-------------+ | 1 | SIMPLE | music_singer_names | index | PRIMARY | singer_name_en | 257 | NULL | 50 | | | 1 | SIMPLE | music_albums | ref | singer_id | singer_id | 4 | test.music_singer_names.id | 1 | Using where | +----+-------------+--------------------+-------+---------------+----------------+---------+----------------------------+------+-------------+ 2 rows in set (0,00 sec)
Учитывая сортировку, левое объединение можно спокойно отбросить
Неактивен
backflip написал:
В принципе понял, что либо то либо то В крайнем случае оставлю пользователей без сортировки и заменю ее фильтрами.
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '`music_singer_names` ORDER BY `singer_name_en` LIMIT 0 , 50 ) msn ON ( `msn` . `' at line 1
Забыл слово FROM во вложенном запорсе. Правильный вариант:
paulus написал:
Query OK, 32768 rows affected
А как Вы сделали 32 тысячи строчек? Я для таких веще пишу скрипт на php, но чувствую, есть способ проще
Неактивен
paulus,
Выполняю:
Отредактированно backflip (15.05.2009 16:23:36)
Неактивен
Хммм... у меня данных, конечно, поменьше.
Давайте попробуем помочь оптимизатору
SELECT SQL_STRAIGHT_JOIN * FROM music_singer_names JOIN music_albums ON (`music_singer_names`.`id`=`music_albums`.`singer_id`) ORDER BY `singer_name_en` LIMIT 0,50;
Неактивен
paulus написал:
SELECT SQL_STRAIGHT_JOIN * FROM music_singer_names JOIN music_albums ON (`music_singer_names`.`id`=`music_albums`.`singer_id`) ORDER BY `singer_name_en` LIMIT 0,50;
Огромнейшее спасибо. STRAIGHT_JOIN помог - все работает как надо.
Думаю, проблема решена.
Неактивен
Добрый день. Немного не в тему, но как это всё через echo вывести? Типа
Музыкант 1
Альбом 1
Альбом 2
...............
Музыкант 2
Альбом 1
Альбом 2
Надо использовать вложенный цикл на альбомы? Может у кого есть пример подобного кода, второй день бьюсь, выводится всё совершенно не так, как хотелось бы.
Неактивен
echo 'Музыкант 1<br>Альбом1<br>...'
Отдельную тему сделайте со структурой базы — тогда получите нормальный ответ
Неактивен