Хобрук: Ваш путь к мастерству в программировании

Это хорошая нормализация базы данных?

Я новичок в использовании mysql, и я пытаюсь изучить лучшие практики. Я установил аналогичную структуру, как показано ниже.

(основная таблица, содержащая все уникальные записи) TABLE = 'main_content'

+------------+---------------+------------------------------+-----------+
| content_id |  (deleted)    | title                        | member_id | 
+------------+---------------+------------------------------+-----------+
|          6 |               | This is a very spe?cal t|_st |      1    |
+------------+---------------+------------------------------+-----------+ 

(Показывает общую сумму каждой сложности и идентификатор соединения --> фактическое имя) TABLE = 'difficulty'

+---------------+-------------------+------------------+
| difficulty_id | difficulty_name   | difficulty_total |
+---------------+-------------------+------------------+
|             1 | Absolute Beginner |                1 |
|             2 | Beginner          |                1 | 
|             3 | Intermediate      |                0 |
|             4 | Advanced          |                0 |
|             5 | Expert            |                0 |
+---------------+-------------------+------------------+

(Эта таблица гарантирует, что для каждой записи можно вставить несколько значений. Например, эта конкретная запись указывает, что с отправкой связаны 2 трудности) TABLE = 'lookup_difficulty'

+------------+---------------+
| content_id | difficulty_id |
+------------+---------------+  
|          6 |             1 |
|          6 |             2 |
+------------+---------------+

Я объединяю все это в читаемый запрос:

SELECT group_concat(difficulty.difficulty_name) as difficulty, member.member_name
FROM main_content
INNER JOIN difficulty ON difficulty.difficulty_id 
IN (SELECT difficulty_id FROM main_content, lookup_difficulty WHERE lookup_difficulty.content_id = main_content.content_id )
INNER JOIN member ON member.member_id = main_content.member_id

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

Когда я запускаю приведенный выше запрос, используя EXPLAIN, он говорит: «Используя где; Использование буфера соединения, а также то, что я использую 2 ЗАВИСИМЫХ ПОДЗАПРОСА (s). Я не вижу способа НЕ использовать подзапросы для достижения того же эффекта, но опять же, я нуб, так что, возможно, есть лучший способ....


  • Почему у main_contant есть FK для сложности И таблица поиска? Не могли бы вы объяснить, что вы пытаетесь построить, чтобы мы могли оценить ваш дизайн? 26.07.2011
  • Мне кажется, что вы можете отказаться от таблицы lookup_difficulty и вместо этого просто использовать составной PK в main_content на (content_id,difficulty_id) 26.07.2011
  • Извините, я хотел удалить этот столбец. Я не использую трудность_id. Я отредактирую сообщение. Я пытаюсь связать все таблицы по существу с main_content.content_id. 26.07.2011
  • @Justin, чтобы оценить ваш дизайн, нам нужно знать, что вы пытаетесь смоделировать. Например, сообщение в блоге с комментариями и т. д. Если мы этого не знаем, мы не можем сказать, подходит ли ваш дизайн для того, что вы пытаетесь сделать. 26.07.2011
  • @cularis Я пытаюсь создать веб-сайт, на который пользователи могут добавлять контент (учебники, руководства, новости и т. д.). Каждый пост попадет в таблицу main_content. Оттуда большинство записей будут идентифицированы по приведенной выше схеме, где 'content_id' ссылается на их опубликованные атрибуты, такие как сложность, приложения и т. д. 26.07.2011

Ответы:


1

Если lookup_difficulty обеспечивает связь между content и difficulty, я бы посоветовал вам удалить столбец difficulty_id из таблицы main_content. Поскольку у вас может быть несколько поисков для каждого content_id, вам потребуется дополнительная бизнес-логика, чтобы определить, какой difficulty_id поместить в вашу таблицу main_content (или несколько записей в таблице main_content для каждого difficulty_id, но это противоречит практике нормализации). Например наибольшее значение/наименьшее значение/случайное значение. В любом случае особого смысла нет.

В остальном стол выглядит нормально.


Обновить

Видел, ты обновил таблицу :)

Просто как примечание. Использование IN может замедлить ваш запрос (IN может привести к сканированию таблицы). В любом случае, раньше так было, но я уверен, что в наши дни компилятор SQL неплохо оптимизирует это.

26.07.2011
  • Спасибо за помощь! В качестве примечания, где я могу узнать типичные скорости, которые использует mysql? Другими словами, как вы узнали, что IN работает медленно? Я могу добиться того же результата, если заменю IN на: = ANY . Я не знаю, что быстрее, и EXPLAIN не дает большого понимания. 26.07.2011
  • @Justin - В основном из опыта и чтения. Есть проприетарное программное обеспечение, которое может анализировать ваши запросы MySQL, а не какие-либо хорошие открытые/бесплатные, о которых я знаю (любой, пожалуйста, не стесняйтесь приводить примеры). 26.07.2011
  • Думаю, я всегда мог бы использовать профайлер. Я буду использовать много объединений для извлечения каждого отправленного контента, поэтому лучше убедиться, что он в какой-то степени оптимизирован. 26.07.2011
  • Если у вас есть профилировщик, который хорошо работает, отлично! Взгляните на запрос @Tudor Constantin. Внутренние соединения обычно могут ускорить выполнение вашего запроса, поскольку каждое соединение уменьшает область поиска. 26.07.2011
  • И последний вопрос, какие поля следует использовать для индексации? В настоящее время все столбцы с _id являются индексами, но я не уверен, что кластерный индекс для таблиц look_up будет лучше. 27.07.2011

  • 2

    Дизайн БД выглядит нормально - что касается вашего запроса, вы можете переписать его исключительно с такими соединениями, как:

    SELECT group_concat(difficulty.difficulty_name) as difficulty, member.member_name
          FROM main_content
            INNER JOIN lookup_difficulty ON main_content.id = lookup_difficulty.content_id
            INNER JOIN difficulty ON difficulty.id = lookup_difficulty.difficulty_id
            INNER JOIN member ON member.member_id = main_content.member_id
    
    26.07.2011
  • Превосходно! Работает нормально, когда ON difficulty.difficulty_id заменяется на ON difficulty.id. Благодарю вас!! После использования EXPLAIN все SELECT_TYPES становятся SIMPLE и не содержат подзапросов. Это именно то, что я искал! 26.07.2011
  • Новые материалы

    Как свинг-трейдеры могут использовать ИИ для больших выигрышей
    По мере того как все больше и больше профессиональных трейдеров и активных розничных трейдеров узнают о возможностях, которые предоставляет искусственный интеллект и машинное обучение для улучшения..

    Как построить любой стол
    Я разработчик программного обеспечения. Я люблю делать вещи и всегда любил. Для меня программирование всегда было способом создавать вещи, используя только компьютер и мое воображение...

    Обзор: Машинное обучение: классификация
    Только что закончил третий курс курса 4 часть специализации по машинному обучению . Как и второй курс, он был посвящен низкоуровневой работе алгоритмов машинного обучения. Что касается..

    Разработка расширений Qlik Sense с qExt
    Использование современных инструментов веб-разработки для разработки крутых расширений Вы когда-нибудь хотели кнопку для установки переменной в приложении Qlik Sense? Когда-нибудь просили..

    React Hooks: основы деструктуризации массива
    Kent C. Dodds написал классный пост о том, как грядущая функция React под названием Hooks работает на капоте. Предстоящий хук React useState основан на деструктурировании массива, давайте..

    Пакеты R, используемые в Tesla
    Добро пожаловать обратно! R — очень популярный язык программирования, используемый множеством компаний, включая Tesla! Итак, давайте взглянем на некоторые пакеты R, которые использует Tesla...

    Сокращение и слияние токенов для эффективных моделей VL: обзор
    Часто в задачах, связанных с компьютерным зрением и НЛП, вычислительно затратная и требующая большого объема памяти обработка становится препятствием для более быстрого логического вывода модели, а..