Вопрос о соединениях и таблицах с миллионами строк - PullRequest
6 голосов
/ 01 мая 2010

Мне нужно создать 2 таблицы:

Журнал (10 миллионов строк с этими столбцами: идентификатор, название, жанры, печать, цена)

Автор (180 миллионов строк с этими столбцами: id, name, magazine_id)

. Каждый автор может писать ТОЛЬКО ОДИН журнал, и у каждого журнала есть больше авторов.

Так что, если я хочу узнать всех авторов журнала Motors, я должен использовать этот запрос:

SELECT * FROM Author, Magazine WHERE ( Author.magazine_id = Magazine.id ) AND ( genres = 'Motors' )

То же самое относится к столбцам Печать и Цена.

Чтобы избежать этих объединений с таблицами миллионов строк, я подумал использовать следующие таблицы:

Журнал (10 миллионов строк с этим столбцом: идентификатор, название, жанры, печать, цена)

Автор (180 миллионов строк в этом столбце: id, name, magazine_id, жанры, печать, цена)

. и этот запрос:

SELECT * FROM Author WHERE  genres = 'Motors' 

Это хороший подход?

Я хочу, чтобы он работал быстрее

Я могу использовать Postgresql или Mysql.

Ответы [ 5 ]

6 голосов
/ 01 мая 2010

Нет, я не думаю, что дублирование информации, как вы описываете, является хорошим дизайном для реляционной базы данных.

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

Это одно из преимуществ нормализации реляционных баз данных для представления информации с минимальной избыточностью, поэтому вы не получите аномалий.

Чтобы сделать это быстрее, я думаю, что вы пытаетесь это сделать, вы должны научиться использовать индексы , особенно , охватывающие индексы .

3 голосов
/ 02 мая 2010

Если вам нужно только получить авторов журнала (и не располагать информацией о журнале), вы можете использовать EXISTS. Некоторые говорят, что EXISTS быстрее, чем JOIN, потому что EXISTS останавливает поиск после первого попадания. Тогда вы должны использовать:

SELECT *
FROM Author
WHERE EXISTS (SELECT 1 FROM Magazine WHERE genres = 'Motor' AND Author.id = Magazine.id)

Кроме того, как упоминалось ранее, указание столбцов ускорит процесс.

2 голосов
/ 01 мая 2010

Это хороший подход?

  1. Плюсы этого подхода перевешивают минусы. Минусы к нормализации (это то, что вы предлагаете) включают в себя:
    • Вы должны поддерживать правильные данные о жанре, печати и ценах для каждого журнала в таблице авторов в любое время, когда они меняются на magazine_id. Это дорого.
    • Вы, очевидно, тратите гораздо больше места для хранения, повторяя данные каждого журнала в среднем 18 раз (это правильное предположение?).
    • Любая другая таблица выбора / обслуживания авторов становится медленнее / дороже.
  2. Ваш запрос не работает. Это должно быть вместо
     SELECT * FROM Author, Magazine 
     WHERE Author.magazine_id = Magazine.id AND genres = 'Motors'
     
  3. Чтобы решить вашу проблему, убедитесь, что у вас есть индекс в журнальном столе по жанрам и индекс magazine_id в таблице авторов
1 голос
/ 02 мая 2010

Вам не нужно делать JOIN, и даже тогда ваш основной запрос неверен. Вы хотели сказать:

SELECT name FROM author
WHERE magazine_id in 
    (SELECT id FROM magazine WHERE genres = 'motors')

Существует много разных способов управления огромными хранилищами данных, подобных этому. Если вы приведете пример того, что вы хотите получить из этих данных, люди могут предложить эффективные способы сделать это.

1 голос
/ 01 мая 2010

Вы должны сделать это:

SELECT * FROM Author
JOIN Magazine ON Author.id = Magazine.id
WHERE genres = 'Motors'

Это должно быть быстро. Если он слишком медленный, убедитесь, что у вас есть все соответствующие индексы, включая индексы первичного ключа в полях идентификатора для всех таблиц и индекс genres.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...