получать по одной записи за раз из объединенной таблицы

#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:

Если содержимое может находиться в нескольких кластерах и количество кластеров может меняться, я думаю, что такое объединение — лучшее решение.

Вы можете попробовать разделить вашу таблицу содержимого на разные таблицы, каждая из которых содержит содержимое определенного кластера, но ее нужно будет часто обновлять.