решено СМОТРЕТЬ НИЖЕ
Я пытаюсь использовать и GROUP BY
, и ORDER BY
в своем запросе, где я получаю данные, отсортированные по сложности.Я должен использовать GROUP BY
из-за GROUP CONCAT
, поскольку некоторые таблицы, такие как 'lookup_peripheral', связывают несколько значений с одним и тем же ключом (content_id).Я понимаю, почему MYSQL не может использовать индекс при выполнении этой задачи, поскольку операторы GROUP BY и ORDER BY не разделяют одно и то же поле.Тем не менее, я ищу альтернативные решения, которые не потребуют дня для получения результатов.
Если я опущу предложение GROUP BY
или ORDER BY
, тогда база данных использует индекс, но в результатах отсутствуют все периферийные устройства или они не отсортированы по сложности.
Я использую таблицу 'lookup_difficulty' в FROM
, поэтому я могу использовать этот индекс при упорядочении результатов.Таблицы lookup_xxxxx
хранят каждое допустимое значение, а затем другие таблицы, такие как peripheral
, связывают отправку со значением через content_id.Все ссылки на представление content_id
.Таблица content
содержит важную информацию, такую как идентификатор участника, имя и т. Д.
Я прошу прощения, если мой пост недостаточно ясен.
mysql> describe peripheral;
+------------------+----------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+------------------+----------+------+-----+---------+-------+
| peripheral_id | int(2) | NO | PRI | NULL | |
| peripheral | char(30) | NO | | NULL | |
| peripheral_total | int(5) | NO | | NULL | |
+------------------+----------+------+-----+---------+-------+
mysql> select * from peripheral;
+---------------+-----------------+------------------+
| peripheral_id | peripheral | peripheral_total |
+---------------+-----------------+------------------+
| 1 | periph 1 | 0 |
| 2 | periph 2 | 1 |
| 3 | periph 3 | 3 |
+---------------+-----------------+------------------+
:
mysql> describe lookup_peripheral;
+---------------+---------+------+------+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+---------------+---------+------+------+---------+-------+
| content_id | int(10) | NO | INDEX| NULL | |
| peripheral_id | int(2) | NO | | NULL | |
+---------------+---------+------+------+---------+-------+
mysql> mysql> select * from lookup_peripheral;
+------------+---------------+
| content_id | peripheral_id |
+------------+---------------+
| 74 | 2 |
| 74 | 5 |
| 75 | 2 |
| 75 | 5 |
| 76 | 3 |
| 76 | 4 |
+------------+---------------+
Ниже не используется индекс для lookup_difficulty, а скорее сортировка таблицы и временная таблица.
SELECT group_concat(DISTINCT peripheral.peripheral) as peripheral, content.member, .....
FROM (lookup_difficulty)
LEFT OUTER JOIN lookup_peripheral ON lookup_difficulty.content_id = lookup_peripheral.content_id
LEFT OUTER JOIN peripheral ON peripheral.peripheral_id = lookup_peripheral.peripheral_id
.....
LEFT OUTER JOIN programmer ON programmer.programmer_id = lookup_programmer.programmer_id
LEFT OUTER JOIN lookup_programming_language ON lookup_difficulty.content_id = lookup_programming_language.content_id
GROUP BY lookup_difficulty.content_id
ORDER BY lookup_dfficulty.difficulty_id
LIMIT 30
Конечная цель - получить результаты, отсортированные по сложности с правильными подключенными периферийными устройствами.Я думаю, что мне нужен подзапрос, чтобы добиться этого.
РЕДАКТИРОВАТЬ: ОТВЕТИТЬ НИЖЕ:
Разобрался.Я сделал то, что подозревал, что должен был сделать, что было добавить подзапрос.Так как MYSQL может использовать только один индекс на таблицу, я не смог собрать вместе GROUP BY
и SORT BY
для моей конкретной настройки.Вместо этого я добавил еще один запрос, который будет использовать другой индекс в другой таблице для группировки периферийных устройств.Вот что я добавил в операторе SELECT
выше:
(SELECT group_concat(DISTINCT peripheral.peripheral) as peripheral
FROM lookup_peripheral
LEFT OUTER JOIN peripheral ON peripheral.peripheral_id = lookup_peripheral.peripheral_id
WHERE lookup_difficulty.content_id = lookup_peripheral.content_id
GROUP BY lookup_peripheral.content_id
LIMIT 1) as peripheral
Я использовал LEFT OUTER
, так как некоторые записи не имеют периферийных устройств.Общее время запроса теперь составляет 0,02 с на процессоре 400 МГц с 128 МБ ОЗУ 100 Гц для базы данных по 40 КБ для большинства таблиц.
EXPLAIN
теперь дает мне USING INDEX
для таблицы lookup_difficulty
.Я добавил это, чтобы добиться этого:
ALTER TABLE `pictuts`.`lookup_difficulty` DROP PRIMARY KEY ,
ADD PRIMARY KEY ( `difficulty_id` , `content_id` )
Edit 2 Я заметил, что при больших смещениях с использованием нумерации страниц страница будет загружаться значительно медленнее.Возможно, вы испытали это и на других сайтах.К счастью, есть способ избежать этого, на что указывает Петр Зайцев .Вот мой обновленный фрагмент кода для достижения тех же временных интервалов для смещений 30K или 0:
FROM
SELECT lookup_difficulty.content_id, lookup_difficulty.difficulty_id
FROM lookup_difficulty
LIMIT '.$offset.', '.$per_page.'
) ld
Теперь просто добавьте ld.whatever
к каждому JOIN
изготовленному, и вот оно!Мой запрос теперь выглядит как полный беспорядок, но по крайней мере он оптимизирован.Я не думаю, что кто-нибудь зайдет так далеко, читая это ...