#mysql #sql
#mysql #sql
Вопрос:
Я хочу получать запись из объединенной таблицы за раз. Но я не надеюсь, что таблицы будут объединены как единое целое.
Фактические таблицы следующие.
table contents -- stores content information.
---- ---------- ---------- ---------- -------------------
| id | name |status |priority |last_registered_day|
---- ---------- ---------- ---------- -------------------
| 1 | content_1|0 |1 |2020/10/10 11:20:20|
| 2 | content_2|2 |1 |2020/10/10 11:21:20|
| 3 | content_3|2 |2 |2020/10/10 11:22:20|
---- ---------- ---------- ---------- -------------------
table clusters -- stores cluster information
---- ----------
| id | name |
---- ----------
| 1 | cluster_1|
| 2 | cluster_2|
---- ----------
table content_cluster -- each record indicates that one content is on one cluster
---------- ---------- -------------------
|content_id|cluster_id| last_update_date|
---------- ---------- -------------------
| 1 | 1 |2020-10-01T11:30:00|
| 2 | 2 |2020-10-01T11:30:00|
| 3 | 1 |2020-10-01T10:30:00|
| 3 | 2 |2020-10-01T10:30:00|
---------- ---------- -------------------
Указывая cluster_id, я хочу получать одно имя содержимого за раз, где contents.status=2 и пара (имя содержимого, cluster_id) находится в content_cluster . Запрос в sql выглядит примерно так: follow .
SELECT contents.name
FROM contents
JOIN content_cluster
ON contents.content_id = content_cluster.content_id
where contents.status = 2
AND content_cluster.cluster_id = <cluster_id>
ORDER
BY contents.priority
, contents.last_registered_day
, contents.name
LIMIT 1;
Однако я не хочу, чтобы таблицы каждый раз соединялись как единое целое, так как мне приходится делать это часто, а таблицы большие. Есть ли какой-либо эффективный способ сделать это? Я могу добавить некоторые индексы к таблицам. Что мне делать?
Комментарии:
1. Помимо инструкций SHOW CREATE TABLE для всех соответствующих таблиц, вопросы о производительности запроса ВСЕГДА требуют ОБЪЯСНЕНИЯ для данного запроса
Ответ №1:
Я бы попробовал написать запрос следующим образом:
SELECT c.name
FROM contents c
WHERE EXISTS (SELECT 1
FROM content_cluster cc
WHERE cc.content_id = c.content_id AND
cc.cluster_id = <cluster_id>
) AND
c.status = 2
ORDER BY c.priority, c.last_registered_day, c.name
LIMIT 1;
Затем создайте следующие индексы:
content(status, priority, last_registered_day, name, content_id, name)
content_cluster(content_id, cluster_id)
.
Цель состоит в том, чтобы план выполнения сканировал индекс для context
каждой строки и просматривал ее, чтобы увидеть, есть ли совпадение content_cluster
. Запрос останавливается при первом совпадении.
Я не могу гарантировать, что это сгенерирует этот план (избегая сортировки), но попробовать стоит.
Ответ №2:
Этот запрос можно легко оптимизировать, применив правильные индексы. Примените операторы alter, которые я упоминаю ниже. И дайте мне знать, значительно ли увеличилась производительность или нет:
alter table contents
add index idx_1 (id),
add index idx_2(status);
alter table content_cluster
add index idx_1 (content_id),
add index idx_2(cluster_id);
Ответ №3:
Если содержимое может находиться в нескольких кластерах и количество кластеров может меняться, я думаю, что такое объединение — лучшее решение.
Вы можете попробовать разделить вашу таблицу содержимого на разные таблицы, каждая из которых содержит содержимое определенного кластера, но ее нужно будет часто обновлять.