Дизайн бази даних: Нова таблиця проти нових стовпців


38

(Це було запропоновано перенести сюди з StackOverflow)

Наразі є таблиця .. і потрібно почати додавати до неї нові стовпці даних. Дані не у кожному записі (навіть після подання нових даних після додавання нових стовпців даних) матимуть дані. Тож мені цікаво, чи більше це підходить для нової таблиці, оскільки це дійсно розширення деяких рядків даних і не застосовується до кожного ряду.

Іншими словами, оскільки для цих нових елементів даних буде багато невикористаних стовпців, здається, що це було б більше підходить для нової таблиці?

Перша таблиця - це кількість переглядів сторінок (наразі 2 мільйони записів)

- ід
- IP-адреса
- переглянуті рази
- created_at часова мітка
- дата

для кожної IP-адреси робиться запис на день - до перегляду разів на день додаються послідовні перегляди сторінок

додаткові поля будуть задані для відстеження точки походження (тобто джерело / середовище / кампанія аналітики Google)

Не кожен візит матиме таку інформацію. Я припускаю, що приблизно 10% рядків матимуть дані (як це зазвичай приписується лише під час першого відвідування)

Основне використання цих даних було б атрибути, звідки люди походять. Це може призвести до частішого використання (що, здається, піддається одній таблиці)

Вдячний за відгук - за потреби можна додати більше

Відповіді:


29

Що ти борешся, це вертикальне перегородка. Це фізична техніка проектування баз даних для підвищення продуктивності. Як і у будь-якій техніці дизайну фізичних баз даних, її застосовність залежить від конкретних запитів, які ви намагаєтеся оптимізувати, і якщо ця методика їх оптимізує. З логічної точки зору, якщо ці нові поля залежать від ключа кандидата для вашої сутності, то це факти, які належать до нього. Спочатку слід переконатися, що ви повністю розумієте функціональну залежність цих нових полів від ваших кандидатських ключів, щоб переконатися, що вони насправді є фактами щоденних переглядів сторінок. Якщо вони є, вирішити розділити їх на іншу таблицю - це оптимізація продуктивності, яку слід проводити, лише якщо вона досягає ваших цілей ефективності.

Взагалі вертикальний розподіл корисний, якщо ви будете запитувати ці нові стовпці нечасто та виразно з інших стовпців у вихідній таблиці. Розмістивши ці стовпці в іншій таблиці, що має той самий ПК, що і ваша існуюча таблиця, ви можете запросити її безпосередньо, коли ви хочете, щоб ці нові стовпці отримали набагато більший пробіг, оскільки у вас буде набагато більше рядків на сторінці на диску для цієї нової таблиці оскільки всі стовпці з початкової таблиці не будуть сидіти на цих рядках. Однак, якщо ви завжди будете запитувати ці стовпці разом із стовпцями в оригінальній таблиці, тоді вертикальний розділ не матиме особливого сенсу, оскільки для їх отримання завжди доведеться зовнішнє з'єднання. Сторінки таблиць на диску надходять у буферний пул СУБД незалежно, ніколи не попередньо з'єднуючись, і так, що приєднання повинно відбуватися при кожному виконанні запиту, навіть якщо дані закріплені в буферному пулі. У цьому сценарії створення їх NULLABLE стовпців у вихідній таблиці дозволило б двигуну зберігання СУБД ефективно зберігати їх при NULL та усунути необхідність приєднання при пошуку.

Мені здається, що ваш випадок використання є останнім, і додавання їх як NULLABLE до вашої оригінальної таблиці - це шлях. Але як і у всьому іншому в дизайні баз даних, це залежить, і для того, щоб прийняти правильне рішення, потрібно знати очікуване навантаження і від того, від чого вдалий вибір залежить. Хорошим прикладом правильного використання для вертикального розділення може бути панель пошуку людей, де у вашій програмі є дуже рідко заселена інформація про людину, яку хтось може захотіти шукати, але рідко. Якщо ви помістите цю інформацію в іншу таблицю, у вас є кілька хороших варіантів ефективності. Ви можете записати пошук так, щоб у вас було 2 запити - один, який використовує основну, завжди заповнену інформацію для пошуку (наприклад, прізвище або ssn), та та, що зовнішня приєднується до дуже рідко заселеної інформації лише тоді, коли її запитують для пошуку. Або ви можете скористатися оптимізатором СУБД, якщо він досить розумний для того, щоб визначити для даного набору змінних хостів, що зовнішнє з'єднання не потрібно і не виконуватиме його, і таким чином вам потрібно створити лише 1 запит.

Яку платформу СУБД ви використовуєте? Те, як платформа обробляє сховище стовпців NULL, оптимізує ваш запит, а також наявність розрідженої підтримки стовпців (це має SQL Server) вплине на рішення. Зрештою, я б рекомендував спробувати обидві конструкції в тестовому середовищі, використовуючи дані про розмір виробництва та навантаження, і побачити, що краще досягає ваших цілей ефективності.


Мені не зрозуміло, що ви маєте на увазі під собою "Однак, якщо ви завжди будете запитувати ці стовпці разом із стовпцями в оригінальній таблиці, тоді вертикальний розділ не матиме особливого сенсу, оскільки вам завжди доведеться зовнішнє з'єднання, щоб отримати їх". зовнішнє з'єднання вам потрібно буде робити лише тоді, коли ви хочете, щоб первинні стовпці були доступні, чи є вторинні стовпчики, чи не є, інакше ви використовуєте ВНУТРІШНЕ ПРИЄДНАННЯ, і це буде корисним у більшості випадків (зменшуючи кількість переглянутих рядків ).
jmoreno

Дякую за всю допомогу тут .. Я фактично пішов із додаванням полів, але, обміркувавши це, я побачив, що я повинен мати ще пару таблиць, щоб краще все визначити. Нарешті, до цього прийшов відвідувач visitor_visits (який має visitor_id і містить джерело) page_views (який має vistor_id та visitor_visit_id), оскільки я хочу знати, яка саме сторінка перегляду віднесена до відвідування, я додав це посилання. Я трохи боровся з цим, але думаю, що це було правильне рішення
cgmckeever

10

Особисто я схиляюся до додавання стовпців до існуючої таблиці. Нова таблиця насправді нічого не купує:

  • ви дійсно не економите багато місця, оскільки значення NULL у вихідній таблиці не займають місця, а новій таблиці потрібен якийсь ідентифікатор, який компенсує будь-яку економію
  • ваші запити ускладнюються ... where newcolumn is not nullстає aleft outer join

У єдиній таблиці це просто означає, що розмір рядка може змінюватись від сторінки до сторінки, але це не повинно впливати на багато існуючих сторінок, особливо якщо ваш кластерний індекс знаходиться на монотонно зростаючому стовпчику (особистість чи дата / час).


Оскільки таблиця наразі не є широкою (на основі вашого опису), і ці дані не стануть занадто широкими, я погоджусь.
HLGEM

4

З огляду на надану вами інформацію, а метою є лише загальна нормалізація, я б, мабуть, просто додавав нульові стовпці, але ви не надали достатньо інформації про те, як дані будуть використані, щоб знати, який найкращий спосіб моделювати дані є.

Залежно від того, як ви реально використовуєте ці дані, ви можете розглянути іншу модель даних. Якщо ви ставите ці дані для звітності, можливо, ви захочете вивчити розмірну модель, яка може бути більш ефективною для певних типів звітності - наприклад, аналіз часу на день добре працює з розподілом розміру дати та часу.

Для відповідей на аналітичні запитання, як-от «який найпопулярніший час дня для відвідувань таких кампаній, як X» або «який день кампанії ми бачимо найбільше відвідувань за годину», жодна колонка даних-часу не працює. дуже добре (але це навіть можна розділити у реляційній моделі), і є багато випадків, коли ви можете ставитися до IP-адреси як до виміру (можливо, з якимись географічними даними у сніжинці).

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.