Чому важлива реляційна модель для бази даних?


61

Я підходжу до проекту, де мені доведеться впроваджувати базу даних зі своїм начальником; ми дуже малий старт, тому робоче середовище є глибоко особистим.

Раніше він дав мені одну з баз даних компанії, і це повністю суперечило тому, про що я навчався (і читав про) у школі для RDBMS. Наприклад, тут є цілі бази даних, які складаються з однієї таблиці (на незалежну базу даних). Одна з цих таблиць має 20+ стовпців і для контексту, ось деякі назви стовпців з однієї таблиці:

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngProductID | vrProductName

Сенс полягає в тому, що там, де він повинен мати окремі таблиці, в яких є дані сутності (ім'я, розмір, дата придбання тощо), він переміщує все це в одну велику таблицю на базу даних.

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

Чому хороша реляційна схема покращує базу даних?


33
Одне слово: Нормалізація.
Роберт Харві

9
Закрийте виборця - виправдайте себе! :-)
Роббі Ді

6
Новим працівникам прийнято критикувати встановлені процедури, не розуміючи причин, що стоять за ними, навіть якщо ці причини не є технічно обгрунтованими. Спершу з’ясуйте, чому ваш бос збудував саме так. Він / вона, можливо, дуже добре знає, що це не гарний дизайн, але не має знань (або, швидше за все, часу), щоб зробити це краще. Будь-які запропоновані вами зміни, ймовірно, будуть отримані більш позитивно, якщо ви з повагою визнаєте причини поточного дизайну.
Педро

5
He [the boss] had given me one of his databases before and it completely went against what I was taught (and read about) in school for RDBMS<- Ласкаво просимо в реальний світ!
Möoz

5
Мені нагадують мою улюблену цитату реляційних баз даних: "Нормалізуйте, поки це болить, денормалізуйте, поки це працює"
Джейк

Відповіді:


70

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

Інший - аргумент розміру пам’яті. Денормалізована таблиця з великою кількістю надмірностей потребує набагато більше місця. Це також грає в аспект ефективності: чим більше у вас даних, тим повільніше будуть ваші запити.

Існує також аргумент, який важче зрозуміти, але насправді важливіший, оскільки ви не можете його вирішити, кинувши на нього більше обладнання. У цьому полягає проблема узгодженості даних. Правильно нормалізована база даних сама по собі подбає про те, щоб продукт із певним ідентифікатором завжди мав те саме ім’я. Але в денормалізованій базі даних такі невідповідності можливі, тому потрібно уникати особливої ​​обережності, коли йдеться про уникнення невідповідностей, що потребує часу на програмування, щоб виправитись, і все-таки викличе помилки, які коштують вам у задоволенні клієнтів.


19
Однією з основних причин денормалізації є зберігання даних , зокрема, якщо у вас є великий обсяг даних, який гарантовано ніколи не змінюється, і ви хочете запитувати їх швидше та ефективніше за рахунок місця для зберігання. Хороша відповідь, це лише FYI для новачків у SQL, які не впевнені, чому нічого іншого, крім 3NF, не бажано.


11
Я не впевнений, чому аргумент послідовності "важче зрозуміти". Мені здається набагато простіше: якщо значення змінюється, то всі копії цього значення повинні бути оновлені. Оновлення однієї копії набагато менше схильних до помилок, ніж оновлення сотень чи тисяч копій одних і тих же даних. Це однаково добре стосується відносин між даними. (Якщо у мене відносини зберігаються двома способами, я повинен оновлювати обидві копії відносин.) Це надзвичайно поширена проблема в денормалізованих БД; це дуже важко запобігти цій корупцію на практиці (виняток матеріалізується використання типу виду).
jpmc26

4
Цей останній абзац слід виділити жирним шрифтом. :-) Без нормалізації неможливо гарантувати цілісність даних. Контроль введення виключно на рівні Business Logic - це дурень, оскільки кожна ненормована база даних в кінцевому підсумку виявляє певну аномалію даних.
DanK

2
@IsmaelMiguel Звичайна практика полягає в тому, що такі базові дані ніколи не важко видаляються з бази даних. Видаліть його лише м'яко, встановивши на ньому прапор, який говорить, що він більше недоступний. У цьому конкретному випадку було б доцільно встановити зв'язок із зовнішнім ключем між продуктами та замовленнями, а це означає, що база даних призведе до помилки при спробі видалити продукт, на який посилаються будь-які замовлення.
Філіпп,

24

Мені доведеться впроваджувати базу даних зі своїм начальником ...

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

lngStoreID | vrStoreName | lngCompanyID | vrCompanyName | lngProductID | vrProductName

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

Але ...

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

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

Цілком можливо відтворити його "перегляд однієї таблиці" даних із .. ну .. Переглядами.


11
Стійкість до єдиної таблиці weltanschauung часто виникає з боку недосвідчених у SQL, які не розуміють приєднань, особливо що стосується відсутніх даних, тобто зовнішніх об'єднань.
Роббі Ді

6
@RobbieDee Найчастіше це люди, які бачили, як денормалізовані дані пошкоджуються, стаючи непослідовними. Я одна така людина. Я б розглядав лише таку структуру в ситуації, що пропонує Філл: це якась таблиця ведення журналів / звітів, де дані ніколи не будуть оновлюватися або лише оновлюватися, видаляючись чистими та повністю відновлюватися з інших джерел.
jpmc26

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

1
@Zach: погодився, тому журнал продажів може бути прийнятним для цього. Припустимо, ви хочете, щоб кожна продаж була пов’язана з тим, що магазин був названий на момент здійснення продажу, а не "поточною назвою магазину", а потім спроба "нормалізувати" це вводить певну значну складність (адже назви магазину, що записує таблицю) потрібен був би серіал із часом, а не лише одне значення на один рівень)
Стів Джессоп

Можливо, головним правилом буде те, що якщо єдина складність, запропонована нормалізацією, полягає в тому, що кілька запитів тепер потребує приєднання до них, щоб забрати всі стовпці, про які потрібно повідомити, то вам слід не бігати, щоб змінити: )
Стів Джессоп

14

Чому хороша реляційна схема покращує базу даних?

Відповідь: це не завжди покращує базу даних. Ви повинні знати, що те, що вас, швидше за все, навчали, називає Третьою Нормальною Формою .

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

Правила 3NF встановлюють зв’язки між даними, які "покращують" базу даних:

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

  2. Він надає спосіб перевірити код (наприклад, відносини "багато в одному" є сигналом для обмеження властивостей / поведінки об'єкта). Коли пишуть код для використання бази даних, іноді програмісти помічають структуру даних як показник того, як повинен працювати їх код. Або вони можуть надати корисні відгуки, якщо база даних не відповідає їх коду. (На жаль, це більше схоже на бажане мислення.)

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

  4. Правильна структура бази даних призводить до поліпшення продуктивності завдяки підключенню даних способами, що мінімізують зберігання даних, мінімізують виклики на зберігання для отримання даних, максимізують ресурси в пам'яті та / або мінімізують сортування / маніпулювання даними для конкретного набору даних, порівняно з запитом, який ви виконання проти цього. Але "правильна" структура залежить від обсягу даних, характеру даних, типу запиту, системних ресурсів тощо. Нормалізуючись, ви можете погіршити продуктивність (тобто якщо ви завантажите всі дані як 1 таблиця - приєднання може уповільнити запит). Обробка транзакцій (OLTP) та бізнес-розвідка (сховище даних) дуже відрізняється.

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

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

Удачі!


4
Незгадане, але я думаю, що важливим моментом для програмістів є те, що для редагування однієї "речі" потрібне редагування лише одного рядка, а не необхідність циклування всієї бази даних, щоб знайти та замінити цю єдину річ.
slebetman

@slebetman У вас ніколи не повинно бути кодового циклу для оновлення декількох рядків в одній таблиці, незалежно від того, нормалізовано це. Використовуйте WHEREпункт. Звичайно, вони все одно можуть піти не так, але це менш вірогідно в нормалізованій ситуації, оскільки вам доведеться відповідати лише одному рядку за допомогою первинного ключа.
jpmc26

@ jpmc26: Цикловою базою даних я маю на увазі побудову запиту для оновлення всіх порушених рядків. Іноді вистачає однієї, де вистачає. Але я бачив нечесні структури, які вимагають підселектів в одну таблицю, щоб отримати всі постраждалі рядки, не впливаючи на рядки, які не повинні змінюватися. Я навіть бачив структури, де жоден запит не може виконати роботу (суб'єкт, який потребує змін, знаходиться у різних стовпцях залежно від рядка)
slebetman

На це питання багато відмінних відповідей, і це не було винятком.
Майк Чемберлен

11

Існує кілька причин, чому використання однієї великої «таблиці богів» є поганою. Спробую проілюструвати проблеми зі складеною прикладом бази даних. Припустимо, ви намагаєтеся моделювати спортивні змагання. Ми скажемо, що ви хочете моделювати ігри та команди, які грають у ці ігри. Дизайн з декількома таблицями може виглядати приблизно так (це за призначенням дуже спрощено, тому не зациклюйтеся на місцях, де можна застосувати більше нормування):

Teams
Id | Name | HomeCity

Games
Id | StartsAt | HomeTeamId | AwayTeamId | Location

і одна база даних таблиць виглядала б так

TeamsAndGames
Id | TeamName | TeamHomeCity | GameStartsAt | GameHomeTeamId | GameAwayTeamId | Location

Спочатку давайте подивимось на складання індексів на цих таблицях. Якщо мені потрібен був індекс про домашнє місто для команди, я міг би легко додати його до Teamsтаблиці чи TeamsAndGamesтаблиці. Пам’ятайте, що кожного разу, коли ви створюєте індекс, його потрібно десь зберігати на диску та оновлювати у вигляді рядків, доданих до таблиці. Що стосується Teamsтаблиці, це досить просто. Я вкладаю нову команду, база даних оновлює індекс. Але про що TeamsAndGames? Ну, те ж саме стосується іTeamsприклад. Я додаю команду, індекс оновлюється. Але це буває і тоді, коли я додаю гру! Незважаючи на те, що це поле буде недійсним для гри, індекс все одно повинен бути оновлений і збережений на диску для цієї гри. Для одного індексу це не дуже погано звучить. Але коли вам потрібно багато індексів для кількох сутностей, забитих у цій таблиці, ви витрачаєте багато місця для зберігання індексів і багато процесорного часу, оновлюючи їх для речей, де вони не застосовуються.

По-друге, узгодженість даних. У разі використання двох окремих таблиць я можу використовувати зовнішні ключі від Gamesтаблиці до Teamsтаблиці, щоб визначити, які команди грають у гру. І якщо припустити, що я роблю колонки HomeTeamIdта AwayTeamIdстовпчики не нульовими, база даних гарантуватиме, що кожна гра, яку я ввожу, має 2 команди та що ці команди існують у моїй базі даних. А як щодо сценарію єдиної таблиці? Ну, оскільки в цій таблиці є кілька сутностей, ці стовпці повинні бути зведені нанівець (ви можете зробити так, щоб вони не були зведені нанівець і не переносили там дані про сміття, але це просто жахлива ідея). Якщо ці стовпці є нульовими, база даних вже не може гарантувати, що коли ви вставляєте гру, вона містить дві команди.

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

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

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

По-третє, майже кожен стовпець повинен бути нульовим або повинен бути заповнений або скопійованими або сміттєвими даними. Гра не потребує TeamNameабо TeamHomeCity. Отже, будь-якій грі потрібен якийсь заповнювач там, або він повинен бути зведеним нанівець. І якщо вона зведена нанівець, база даних із задоволенням прийме гру без " TeamName. Це також візьме команду без імені, навіть якщо ваша бізнес-логіка говорить, що цього ніколи не повинно відбуватися.

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

Нарешті, розробіть щось, що легко буде підтримувати. Тільки тому, що це "працює", не означає, що це нормально. Намагатися підтримувати богові таблиці (як і заняття богом) - це кошмар. Ви просто налаштовуєте себе на біль пізніше.


1
"Команди: Id | Назва | HomeCity". Просто переконайтеся, що ваша схема даних не робить вашу заявку неправильно заявляти, що Super Bowl XXXIV був виграний LA Rams. Тоді як SB XXXIV повинен з’являтись у запиті на всі чемпіонати, виграні командою, яка на даний момент називається LA Rams. Є кращі і гірші «богові таблиці», і ви, звичайно, подарували поганий. Кращим було б "Ідентифікатор гри | Назва домашньої команди | Місто команди команди | Назва команди | Гость команди міста | Гра починається з | тощо ...". Це виникає як перша спроба моделювання інформації на кшталт "Нові Орлеанські святі @ Чикагські ведмеді 1п Східна".
Стів Джессоп

6

Цитата дня: " Теорія і практика повинні бути однаковими ... теоретично "

Денормалізований стіл

Ваша унікальна таблиця утримує все, що містить зайві дані, має одну перевагу: вона робить звіт про свої рядки дуже простим для кодування та швидким виконанням, оскільки вам не потрібно робити жодних з'єднань. Але це за високу вартість:

  • Він містить зайві копії відносин (наприклад, IngCompanyIDта vrCompanyName). Оновлення основних даних може потребувати оновлення набагато більше рядків, ніж у нормалізованій схемі.
  • Це все змішує. Ви не можете забезпечити простий контроль доступу на рівні бази даних, наприклад, гарантуючи, що користувач A може оновлювати лише інформацію про компанію, а користувач B - лише інформацію про продукт.
  • Ви не можете забезпечити правила узгодженості на рівні бази даних (наприклад, первинний ключ для підтвердження того, що існує лише одне ім’я компанії для ідентифікатора компанії).
  • Ви не повністю користуєтеся оптимізатором БД, який міг би визначити оптимальні стратегії доступу для складного запиту, скориставшись розміром нормованих таблиць та статистикою декількох індексів. Це може швидко компенсувати обмежену перевагу уникнення приєднання.

Нормована таблиця

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

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


5

Я думаю, що у вашому питанні є принаймні дві частини:

1. Чому об'єкти різних типів не повинні зберігатися в одній таблиці?

Найважливіші відповіді тут - читабельність коду та швидкість. A SELECT name FROM companies WHERE id = ?- це набагато легше для читання, ніж SELECT companyName FROM masterTable WHERE companyId = ?ви, і ви менше шанси на випадкове запитання дурниць (наприклад, SELECT companyName FROM masterTable WHERE employeeId = ?це не було б можливо, коли компанії та працівники зберігаються в різних таблицях). Що стосується швидкості, то дані з таблиці бази даних отримують або шляхом читання повної таблиці послідовно, або зчитування з індексу. І те й інше швидше, якщо таблиця / індекс містить менше даних, і це так, якщо дані зберігаються в різних таблицях (і вам потрібно прочитати лише одну з таблиць / індексів).

2. Чому суб'єкти одного типу повинні бути розділені на суб-сутності, які зберігаються в різних таблицях?

Тут причина, головним чином, у запобіганні невідповідності даних. При підході до єдиної таблиці для системи управління замовленнями ви можете зберігати ім'я клієнта, адресу клієнта та ідентифікатор продукту, який клієнт замовив як єдину сутність. Якщо клієнт замовив кілька продуктів, у вас у базі даних буде кілька примірників імені та адреси клієнта. У кращому випадку у вашій базі даних ви просто отримали дублікати даних, що може трохи уповільнити їх. Але ще гірший випадок - те, що хтось (або якийсь код) помилився, коли дані були введені таким чином, що компанії стикаються з різними адресами у вашій базі даних. Це одне досить погано. Але якщо ви запитували адресу компанії на основі її назви (наприклад,SELECT companyAddress FROM orders WHERE companyName = ? LIMIT 1) ви просто довільно отримаєте одну з двох повернених адрес і навіть не зрозумієте, що є невідповідність. Але щоразу, коли ви запускаєте запит, ви можете отримувати іншу адресу, залежно від того, як ваш запит вирішується внутрішньо СУБД. Це, швидше за все, порушить вашу програму десь в іншому місці, і першопричину цієї поломки буде дуже важко знайти.

При підході до декількох таблиць ви розумієте, що функціональна залежність від назви компанії до адреси компанії (якщо компанія може мати лише одну адресу), ви збережете кордон (companyName, companyAddress) в одній таблиці (наприклад, company), а також (productId, companyName) вмістити в іншу таблицю (наприклад order). UNIQUEОбмеження на companyстолі може потім забезпечувати , що кожна компанія має тільки одну адресу в базі даних , так що ніякого невідповідності адрес компанії ніколи не може виникнути.

Примітка. На практиці з міркувань ефективності ви, ймовірно, генеруєте унікальний ідентифікатор компанії для кожної компанії та використовуєте її як зовнішній ключ, а не безпосередньо використовуєте companyName. Але загальний підхід залишається колишнім.


3

TL; DR - Вони розробляють базу даних на основі того, як їх навчали, коли вони навчалися в школі.

Я міг би написати це запитання 10 років тому. Мені знадобилося певний час, щоб зрозуміти, чому мої попередники проектували свої бази даних так, як вони робили. Ви працюєте з ким-небудь, що:

  1. Здобули більшість своїх навичок проектування баз даних, використовуючи Excel як базу даних або
  2. Вони використовують найкращі практики, коли вони закінчили школу.

Я не підозрюю, що це №1, оскільки у вас на ділі є ідентифікаційні номери, тому я вважаю, що №2.

Після закінчення школи я працював у магазині, в якому використовувався AS / 400 (він же IBM i). Я знайшов деякі дивні речі в тому, як вони розробляли свої бази даних, і почав виступати за те, щоб ми вносили зміни, щоб слідкувати за тим, як мене вчили, як проектувати бази даних. (Я тоді був німий)

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

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


Деякі приклади того, з чим я стикався, що не відповідав реляційній моделі:

  • Дати зберігалися у вигляді днів Джуліана, які потребували приєднання до таблиці дати, щоб отримати фактичну дату.
  • Денормалізовані таблиці з послідовними стовпцями одного типу (наприклад code1,code2, ..., code20)
  • Стовпці CHAR NxM довжини, що представляють масив з N рядків довжиною M.

Причини, які мені давали для тих дизайнерських рішень, базувалися на обмеженнях системи, коли база даних була вперше розроблена.

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

Послідовні стовпці одного типу - середовище програмування, в якому вони були, дозволило програмі створити змінну масиву над частиною рядка. І це був простіший спосіб зменшити кількість операцій зчитування.

Стовпці довжини CHAR NxM - простіше було перемістити значення конфігурації в один стовпець, щоб зменшити операції зчитування файлів.

Слабо продуманий приклад в еквіваленті С, що відображає середовище програмування, яке вони мали:

#define COURSE_LENGTH 4
#define NUM_COURSES 4
#define PERIOD_LENGTH 2

struct mytable {
    int id;
    char periodNames[NUM_COURSES * PERIOD_LENGTH];  // NxM CHAR Column
    char course1[COURSE_LENGTH];
    char course2[COURSE_LENGTH];
    char course3[COURSE_LENGTH];
    char course4[COURSE_LENGTH];
};

...

// Example row
struct mytable row = {.id= 1, .periodNames="HRP1P2P8", .course1="MATH", .course2="ENGL", .course3 = "SCI ", .course4 = "READ"};

char *courses; // Pointer used to access the sequential columns
courses = (char *)&row.course1;


for(int i = 0; i < NUM_COURSES; i++) {

    printf("%d: %.*s -> %.*s\n",i+1, PERIOD_LENGTH, &row.periodNames[PERIOD_LENGTH * i], COURSE_LENGTH,&courses[COURSE_LENGTH*i]);
}

Виходи

1: HR -> MATH
2: P1 -> ENGL
3: P2 -> SCI
4: P8 -> ЧИТАТИ

Згідно з тим, що мені сказали, деяке з цього часу вважалося найкращою практикою.

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