Чи погана практика об’єднання даних з різних таблиць в одну?


12

Фон

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

Проблема

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

Моє "Рішення"

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

Таблиця буде тоненькою і довгою, зберігаючи лише необхідні дані, приблизно так:

CREATE TABLE dbo.HCM_Event_Log (
    id INT IDENTITY,
    type_id INT NULL,
    orig_id VARCHAR(36) NULL,
    patient_id UNIQUEIDENTIFIER NOT NULL,
    visit_id UNIQUEIDENTIFIER NULL,
    lookup_id VARCHAR(50) NULL,
    status VARCHAR(15) NULL,
    ordered_datetime DATETIME NULL,
    completed_datetime DATETIME NULL,
    CONSTRAINT PK_HCM_Event_Log PRIMARY KEY CLUSTERED (id)
)

Тоді я мав би різні реляційні таблиці для таких речей, як type_id та групи елементів.

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

Моє запитання

Це погана чи хороша ідея? Я розумію, що в SQL Server (2008 р2 Standard Edition BTW) кожна ситуація різна, і правило "інколи", але я дійсно просто шукаю загальну пораду.

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


1
Чи можете ви виконати заплановані відключення? Якщо жодне з цих оновлень не зможе зняти тригер, і ви не оновлюватимете свої агрегати, що може призвести до поганих даних.
Ерік

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

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

Вибачте за пізню відповідь, хлопці, дякую за відгуки. @Erik - Так, ми запланували оновлення, і я перевіряю, чи всі мої попередні зміни все ще відбулися через ряд сценаріїв контрольного списку, які я запускаю, так що сюрпризів там не буде, і я буду зберігати CREATE сценарії для всі тригери.
jreed121

@MichaelGreen - Я розгляну схему зірок, але мені цікаво, чому ти вважаєш, що всі ці дані в одній таблиці - це погана ідея? Середовище додатків повністю ізольовано у VPN, воно жодним чином недоступне за межами мережі. Якщо з таблицею щось піде не так, то це ще не кінець світу, тому що я можу просто написати все до нього. Таблиця не буде використовуватися для критично важливих даних, або, принаймні, це не буде єдиним, не первинним місцем зберігання даних.
jreed121

Відповіді:


8

Якщо я вас правильно зрозумів,

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

Я підійшов би до цього так:

  • Створіть власну окрему базу даних, над якою я повністю контролюю.
  • Налаштуйте процес синхронізації, який зчитує дані з відповідних таблиць і стовпців із сторонньої бази даних та вставляє / оновлює в мою.
  • Розробіть мої складні звіти на основі стійкої структури моєї бази даних.

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

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

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

оновлення

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

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

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

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

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


Якщо ви проходите пакетний шлях передачі, ми мали успіх у відстеженні змін (та зміні збору даних, залежно від ваших потреб) при досить великій кількості транзакцій (100 Кб на день). Це простіше, ніж реалізувати власні таблиці постановки / аудиту / розбіжності, і їх можна розгорнути без зміни коду програми чи тригерів.
Майкл Грін

Будь то тригери чи CDC, єдиний спосіб, коли ви дійсно наблизитесь до реального часу, - це потокове передавання чи черга. На основі черги - хороший компроміс щодо затримки та економічної ефективності. Ваш час буде витрачено на методи швидшої обробки черги. залишаючи більшу частину роботи асинхронною від програми та зменшуючи навантаження на користувацькі транзакції. У минулому я робив це дуже проти програми Allscripts Sunrise EMR сервісом, який обробляв чергу з деякими паралельними C # дзвінками. типова затримка на обробку нових даних, що підлягають обробці та наявні на складі, була нижчою 30 сек.
Бред Д

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

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

3

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

Як уже згадували інші, не використовуйте тригери, синхронізуйте в партіях.

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

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


3

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

З позитивного боку:

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

Однак є і мінуси:

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

2

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

Тригери мають стільки проблем, що вам слід їх уникати:

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

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


1. Тригери були б простими, тому викинуті помилки були б мінімальними, якщо вони взагалі існували. 2. Сам тригер не буде обробляти декілька рядків (IE один рядок, оновлений у таблиці з тригером, не спричинить оновлення декількох рядків в іншому місці), але декілька рядків можна буде вставити / оновити / видалити одразу в джерело таблиця - це ви маєте на увазі? 3. з цим не вдалося впоратися NOCOUNT? 4. У таблиці призначення не буде жодних тригерів, і я можу забезпечити те саме для інших.
jreed121

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