Перший дизайн баз даних: чи я переоблаштовую? [зачинено]


246

Фон

Я студент першого курсу, і працюю неповний робочий день для малого бізнесу тата. Я не маю досвіду в розробці додатків у реальному світі. Я написав сценарії в Python, деякі курсові роботи на C, але нічого подібного.

У мого тата є невеликий навчальний бізнес, і зараз усі заняття заплановані, записуються та проводяться через зовнішню веб-програму. Існує функція експорту / "звітів", але вона є загальною, і нам потрібні конкретні звіти. У нас немає доступу до фактичної бази даних для запуску запитів. Мене попросили створити власну систему звітності.

Моя ідея - створити загальний CSV-експорт та імпорт (можливо, з Python) їх у базу даних MySQL, що розміщується в офісі щовечора, звідки я можу запускати конкретні запити, які потрібні. Я не маю досвіду роботи з базами даних, але розумію основи. Я трохи прочитав про створення бази даних та звичайні форми.

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

Схема, яку я придумала, така:

  1. З точки зору клієнта:
    • Клієнти - це основна таблиця
    • Клієнти пов'язані з відділом, в якому працюють
      • Департаменти можуть бути розкидані по країні: HR в Лондоні, Маркетинг у Свонсі тощо.
      • Департаменти пов'язані з підрозділом компанії
    • Підрозділи пов'язані з материнською компанією
  2. З точки зору занять:
    • Сесії - це основна таблиця
      • Викладач пов'язаний з кожним заняттям
      • Кожному сеансу надається statusid. Наприклад 0 - завершено, 1 - скасовано
      • Сесії групуються в "пакети" довільної величини
    • Кожен пакет призначається клієнту

Я «сконструював» (більше схожий на накреслений) схему на аркуші паперу, намагаючись тримати її нормалізованою до 3-го класу. Потім я підключив його до MySQL Workbench, і це зробило все для мене гарним:
( Клацніть тут для повнорозмірної графіки )

alt текст
(джерело: maian.org )

Приклад запитів я буду виконувати

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

Питання (и)

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

Дякую за ваш час


131
Шановний студент першого курсу: будь ласка, продовжуйте використовувати StackOverflow. Ваше запитання цікаве, добре написане та корисне. Іншими словами, ви знаходитесь в першій 1% запитань.
Адам Кросленд

Чи може відділ містити інші підрозділи? Якщо це так, таблиця "має" може бути використана для прив'язки відділу назад до відділу, який він містить
Марк Шультейс

Дякую за добрі коментарі :) Позначте, мені доведеться ще раз переглянути документацію для цього проекту, але я не думаю, що ми визначили цей випадок. Дякуємо, що вказали на це.
bob esponja

1
Мені не подобаються конгреси, що називають ваш основний ключ. таблиця divisionsмає стовпчик з ім'ям divisionid. Ви не вважаєте це зайвим? Просто назвіть це id. також імена вашої таблиці, включаючи _has_: я б видалив це і просто назвав його, наприклад cities_departments. ваші DATETIMEстовпці повинні мати тип, TIMESTAMPякщо вони не є значеннями для введення користувачем. Я думаю, що це гарна ідея мати citiesта countriesтаблиці. ви можете зіткнутися з проблемою, обмежуючи таблиці єдиною status. Подумайте про використання INTта виконайте побізні порівняння на ньому, тож ви можете там провести більше значення
Джеймс

@binnyb Існує багато аргументів щодо використання id як імені первинного ключа, який люди повинні розглянути, перш ніж приймати рішення.
Джедай

Відповіді:


42

Ще кілька відповідей на ваші запитання:

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

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

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

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

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


1
1. Дякую, це заспокоює! 2 та 3. Я досі не знаю, як працюють індекси, це те, що я планував прочитати. Якщо у нас коли-небудь буде "проблема" досягти мільйона записів, можливо, буде бюджет найняти досвідчених розробників: P Дякую за розуміння різних db ролей, які існують, для мене це все нове і дуже цікаво знати. Я розгляну знімки, оскільки те, що ви описуєте, в основному є кінцевою метою проекту.
bob esponja

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

14

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

Що можна зробити - це у таблиці Департаменти, додати CityId та DivisionId.

Крім того, я думаю, що все добре ...


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

1
Так, я згоден ..... але це звучало так, що відділ може бути лише в одному місті / районі. Якщо ні, то те, що він мав, було безумовно правильно.
Преосвященний Гонзо

У мене є вікі-стаття, яку я написав з "спец" в офісі, мені доведеться її прочитати ще раз, але Якоб Г правильно, IIRC є деякі відділи, які охоплюють підрозділи. Один відділ кадрів з батьків ACME як для охорони здоров'я ACME, так і для догляду за тілом ACME. Якщо я можу спростити це, хоча, безумовно, буду, дякую за пропозицію.
bob esponja

6

Єдині зміни, які я б вніс, - це:
1. Змініть свій VARCHAR на NVARCHAR; якщо ви, можливо, будете міжнародними, вам може знадобитися unicode.

2- Змініть свій ідентичний код на GUID (унікальний ідентифікатор), якщо це можливо (це може бути моїм особистим уподобанням). Якщо припустити, що ви зрештою дістанетесь до того, що у вас є декілька середовищ (dev / test / staging / prod), можливо, ви захочете перенести дані з одного в інший. Має ідентифікатори GUID значно полегшує це.

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

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


1- Дякую, у мене виникли проблеми з діакритикою та UTF8, щодо яких я збирався поставити ще одне питання. Можливо, це питання. 2- Я прочитав тут деякі інші питання на ЗУ з великою кількістю суперечливих думок з цього питання, я буду більше читати з цього приводу. 3- Я ще раз про це поговору з батьком, дивлячись на "специфікацію", яку я написав, і переконуюсь, чи є це те, що ми повинні вивчити. Наступний коментар
Cob'd

4- Я не вдавався в це в головному питанні стислості: статус клієнта полягає в тому, чи вони активні (залишилися сеанси) чи неактивні (сеансів немає). Для більшої ясності ви маєте на увазі більш описову назву для кола? Наприклад, enrolment_status? Дякуємо за ваш внесок
bob esponja

re # 4- Окрім вашого більш чіткого імені, якщо є лише два стани, активне / неактивне, то чому б просто не зробити його трохи стовпчиком?
Яків Г

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

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

6

Ні. Схоже, ви проектуєте з хорошим рівнем деталізації.

Я думаю, що країни та компанії - це та сама сутність у вашому дизайні, як і міста та відділи. Я позбудусь таблиць країн і міст (і міст_Has_Departments) і, якщо потрібно, додамо бульовий прапор IsPublicSector до таблиці компаній (або стовпчик CompanyType, якщо більше варіантів, ніж просто приватний сектор / громадський сектор).

Крім того, я думаю, що у використанні таблиці відділів є помилка. Схоже, таблиця відділів служить посиланням на різні види відділів, які може мати кожен відділ клієнтів. Якщо це так, його слід називати DepartmentTypes. Але ваші клієнти (які, я припускаю, відвідувачі) не належать до відділу TYPE, вони належать до фактичного примірника відділу в компанії. Наразі ви знаєте, що даний клієнт десь належить до відділу кадрів, а не до якого!

Іншими словами, Клієнтів слід пов’язати з таблицею, яку ви називаєте Відділи_Хас_Департаменти (але яку я назвав би просто Департаменти). Якщо це так, то ви повинні розбити міста на підрозділи, як обговорювалося вище, якщо ви хочете використовувати стандартну референтну цілісність у базі даних.


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

RE: описує таблицю, мій оригінальний роздум про те, щоб використовувати його як фактичні відділи, назва типу департаменту. Мені не прийшло в голову просто мати типи відділів, що здається більш логічним. Зрештою, знаючи, до якого відділу і де хто належить, я думав, що зв’язок департаменту з містом та відділом (який пов'язаний з компанією) працював би. Я помилявся? Деякі підрозділи розбивають міста на поділи, які охоплюють декілька міст, і я думаю, можливо, навіть країни. Я ще раз загляну в це. Дякуємо за ваш внесок
bob esponja

5

До речі, варто зауважити, що якщо ви вже генеруєте CSV-файли і хочете завантажити їх у базу даних mySQL, LOAD DATA LOCAL INFILE - ваш найкращий друг: http://dev.mysql.com/doc/refman/5.1/ uk / load-data.html . Mysqlimport також варто вивчити, і це інструмент командного рядка, який в основному є гарною обгорткою навколо завантаження даних про завантаження.


3

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

І ще одне: чи вірите ви, що вам справді потрібні таблиці "міст" та "країн"? Чи не матиме стовпці "місто" та "країна" у таблиці відділів, чи достатньо для ваших випадків використання? Наприклад, чи потрібно вашій заяві перераховувати відділи за містами та містами по країнах?


1
Спробуйте, як я міг, він продовжує приймати надмірні обчислення великого O helloworld.c, оптимізує таблиці міст і країн, які просто породили себе, коли я виконував кроки, щоб отримати базу даних 3NF. Я думаю, що перевага, яку вони пропонують, - це узгодженість назв міст / країн. Начебто, якщо ми знайдемо клієнта в Мюнхені, і хтось із тих, хто вводить нового учня до системи планування, вирішить назвати його Мюнхеном замість Мюнхена, як для попередніх студентів. Також нам може знадобитися перерахувати відділи по містах, мені доведеться перевірити. Дякую.
bob esponja

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

1
Я не сказав, що він не повинен робити стрес-тест на свій дизайн :)
Ганс Вестербек

3

Наступні коментарі на основі ролі спеціаліста з бізнес-аналітики / звітності та менеджера стратегії / планування:

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

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

  3. Інформація про компанію може використовувати багато інших полів, включаючи очевидну адресу / телефон / тощо. інформація. Я також буду готовий додати в колонки D&B "DUNs" (Сайт / відділення / Ultimate) довгостроковий термін, Dun and Bradstreet (D&B) має величезний каталог компаній, і ви дізнаєтесь згодом у дорозі, їх інформація дуже корисна. для звітування / аналізу. Це допоможе вирішити проблему з декількома поділами, яку ви згадуєте, і дозволить згорнути їх ієрархію для підрозділів / відділень / гілок / тощо. великого корпусу.

  4. Ви не згадуєте, з якою кількістю записів ви будете працювати, що може означати налаштування себе на велику ініціативу розвитку, яка могла б зробити швидше і набагато менше головних болів із заздалегідь встановленим програмним забезпеченням для "звітування". Якщо ви не маєте великої кількості баз даних (<65000), переконайтесь, що MS-Access, OpenOffice (Base) або пов'язані з ними рішення для розробників звітів / додатків не змогли зробити цього. Я безкоштовно використовую безкоштовне програмне забезпечення APEX від Oracle, він постачається з їх безкоштовною базою даних Oracle XE, просто завантажуючи його з свого сайту.

  5. FYI - Звіт про звіт: для великих баз даних, як правило, є два екземпляри бази даних: a) База даних транзакцій для запису кожного детального запису. б) база даних звітів (март даних / сховище даних), розміщена на окремій машині. Для отримання додаткової інформації шукайте google і зіркову схему, і схему Сніжинки.

З повагою


1. Ви маєте на увазі додавання всіх цих стовпців до клієнтської таблиці? Я думаю, що це порушить нормалізацію, а також ускладнить дотримання послідовності, але я не впевнений, що я правильно зрозумів. 2. Пакети є послідовними, лише останній пакет може мати непогашені кредити, тому не потрібно відстежувати кілька пакетів. Ви все-таки рекомендуєте зберігати його в клієнтській таблиці в цьому випадку? 3. Це здається, що буде дуже корисно з'ясувати структуру компаній-клієнтів, я розглядаю це завдяки.
bob esponja

4. Мені доведеться перевірити кількість клієнтів і сесій, які ми очікуємо на наступний рік, але мені здається можливим, щоб таблиця сесій досягла стількох рядів за рік або близько того. Я перегляну програмне забезпечення для звітування, мені це не прийшло в голову. 5. Здається, це ситуація, до якої я потрапив випадково; веб-додаток буде нашою "базою даних транзакцій", а цей проект - нашою "базою даних про репонування" :) Дякуємо за ваш внесок.
bob esponja

1. Так, додаючи стовпці "Ідентифікатор компанії, Опис відділу, Опис відділу, Ідентифікатор типу відділу, Ідентифікатор типу відділу" до таблиці клієнтів. Клієнт належить одній компанії, окремому типу відділу (IT / Ops / Admin / тощо) в межах компанії та окремому типу підрозділу (Продажі / HR / Маркетингові напрямки бізнесу). 2. Я просто думаю, що Кредит асоціюється з клієнтом чи компанією, а не з пакетом сесій. Це ділове рішення, яке ви можете прийняти.
Буде чи

Ларрі також згадав про поєднання компанії та країни. Я повністю погоджуюсь і повертаюся до точки зору посилань на науково-дослідні роботи Я б використовував SiteID або щось унікальне, щоб дозволити кілька місць однієї компанії, а потім зв’язати Департаменти з одним із унікальних SiteID.
Буде чи

2

Я хочу вирішити лише стурбованість тим, що приєднання до безглуздих таблиць спричинить хіт ефективності. Не бійтеся нормалізуватися, тому що вам доведеться робити приєднання. Приєднання нормальні і очікувані в реляційних датах, і вони розроблені для того, щоб добре їх обробляти. Вам потрібно буде встановити відносини PK / FK (для цілісності даних це важливо враховувати при розробці), але у багатьох базах даних FK не індексуються автоматично. Оскільки вони будуть використовуватися при з'єднанні, ви, безумовно, хочете почати з індексації FKS. ПК зазвичай отримують індекс про створення, оскільки вони повинні бути унікальними. Це правда, що дизайн сховища даних зменшує кількість приєднань, але, як правило, не доводиться зберігати дані, доки в одному звіті не буде мільйонів записів. Навіть тоді майже всі сховища даних починають використовувати транзакційну базу даних для збору даних у режимі реального часу, а потім дані переміщуються на склад за графіком (щоночі або щомісяця або все, що потрібно бізнесу). Тож це хороший початок, навіть якщо вам потрібно пізніше розробити сховище даних для підвищення продуктивності звіту.

Треба сказати, що ваш дизайн вражає студентів першого курсу.


1

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


перерахунки злі. Кожен раз, коли вам потрібно розширити перерахунок, вам доведеться перебудовувати свою таблицю - це нормально, поки ваша таблиця не набере розміру на багато ГБ.
Мартін

Дякую за внесок та пропозицію, Кріс, я побоювався, що буду створювати надто складне чудовисько. Мартине, статуси досить чітко визначені та статичні: в основному клас 0-завершений, 1-й клас скасований, 2-не з'явився. Я думаю, що ці троє охоплюють будь-який можливий результат класу. Чи все-таки погана ідея використовувати переписки в цьому випадку?
bob esponja

Це здається ідеальним для перерахунків. Усі можливі результати достроково задовольняються. Інт також є прекрасним, який ви можете представити перерахунком або статичними вкладками у вашій програмі. Насправді це не важливо :) Енумам приємніше дивитися, якщо ви редагуєте свою базу даних за допомогою якогось інструмента.
Кріс Деннетт

перерахунки можуть бути проблематичними (можливо, зло занадто сильне слово), коли у вас є великі таблиці, які повинні бути в режимі онлайн 24x7, і перерахування потрібно змінити. Зважаючи на те, що ви переселяєте таблиці з нуля - не хвилюйтеся з цього приводу. Враховуючи достатньо невеликий набір даних, ви також можете просто використовувати рядки.
Мартін

1

Я працював у навчальній / шкільній області, і я вважав, що хочу зазначити, що взагалі існує зв'язок M: 1 між тим, що ви називаєте "сеансами" (екземплярами заданого курсу), і самим курсом. Іншими словами, у вашому каталозі пропонується курс ("іспанська 101" чи будь-який інший), але у вас можуть бути два різних екземпляри його протягом одного семестру (Tu-Th викладає Сміт, Ср-Пт викладає Джонс).

Крім цього, це виглядає як вдалий старт. Б'юсь об заклад, ви виявите, що домен клієнта (графіки, що ведуть до "клієнтів") складніший, ніж ви моделювали, але не перестарайтеся з цим, поки у вас не з’являться реальні дані, які б вас орієнтували.


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

0

Кілька речей прийшли до тями:

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

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

  3. Концепція "пачки" зовсім не зрозуміла.

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

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