SQL або NoSQL? А також найскладніші SELECT-запити

  • 6 января, 15:11
  • 2985
  • 0

Чи є NoSQL бази майбутнім програмування? Або кожній технології відведено своє місце? Відповідаємо на ці питання в статті.

Чи є NoSQL бази майбутнім програмування? Або кожній технології відведено своє місце? Відповідаємо на ці питання в статті.

Типи NoSQL

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

Більш того, конкретна база може використовувати відразу декілька технологій. Наприклад, AWS DynamoDB є одночасно документною, типом ключ-значення і з широким стовпцем, а Azure Cosmos DB - графовою і документною. На ринку величезна кількість баз, і така різноманітність ставить важке завдання перед архітекторами БД. 

Переваги SQL

Щоб зробити вибір, потрібно згадати 3 нормальні форми реляційних баз, більш складні форми можна поки опустити:

1 форма:

  • Інформація в кожному осередку повинна бути неподільною.
  • Рядки повинні бути унікальні і однозначно визначені головним ключем.

2 форма:

  • Всі атрибути в рядку повинні залежати від ключа або від всіх його полів, якщо ключ складовою.

3 форма:

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

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

  • Для неструктурованих і напівструктурованих даних з'являється необхідність додавати дані в окремі рядки, а не в усі. Це завдання ускладнюється довільним типом доданих даних, що заважає дотримуватися атомарності.
  • При об'єднанні великих таблиць продуктивність може помітно знижуватися.
  • При необхідності масово оновити дані в великій кількості пов'язаних таблиць з'являється місце, яке гальмує всю роботу.

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

SELECT
        CONCAT(p1.id, p1.tvab) + 0 AS tvid,
        CONCAT(p1.christian_name, " ", p1.surname) AS Name,
        p1.postal_code AS Code,
        p1.city AS City,
        pg.abrev AS Area,
        IF(td.participation = "Aborted", "A", " ") AS A,
        p1.dead AS dead1,
        l.event AS event1,
        td.suspect AS tsuspect1,
        id.suspect AS isuspect1,
        td.severe AS tsevere1,
        id.severe AS isevere1,
        p2.dead AS dead2,
        l2.event AS event2,
        h2.nurse AS nurse2,
        h2.doctor AS doctor2,
        td2.suspect AS tsuspect2,
        id2.suspect AS isuspect2,
        td2.severe AS tsevere2,
        id2.severe AS isevere2,
        l.finish_date
FROM
        twin_project AS tp
        /* For Twin 1 */
        LEFT JOIN twin_data AS td ON tp.id = td.id
                  AND tp.tvab = td.tvab
        LEFT JOIN informant_data AS id ON tp.id = id.id
                  AND tp.tvab = id.tvab
        LEFT JOIN harmony AS h ON tp.id = h.id
                  AND tp.tvab = h.tvab
        LEFT JOIN lentus AS l ON tp.id = l.id
                  AND tp.tvab = l.tvab
        /* For Twin 2 */
        LEFT JOIN twin_data AS td2 ON p2.id = td2.id
                  AND p2.tvab = td2.tvab
        LEFT JOIN informant_data AS id2 ON p2.id = id2.id
                  AND p2.tvab = id2.tvab
        LEFT JOIN harmony AS h2 ON p2.id = h2.id
                  AND p2.tvab = h2.tvab
        LEFT JOIN lentus AS l2 ON p2.id = l2.id
                  AND p2.tvab = l2.tvab,
        person_data AS p1,
        person_data AS p2,
        postal_groups AS pg
WHERE
        /* p1 gets main twin and p2 gets his/her twin. */
        /* ptvab is a field inverted from tvab */
        p1.id = tp.id AND p1.tvab = tp.tvab AND
        p2.id = p1.id AND p2.ptvab = p1.tvab AND
        /* Just the sceening survey */
        tp.survey_no = 5 AND
        /* Skip if partner died before 65 but allow emigration (dead=9) */
        (p2.dead = 0 OR p2.dead = 9 OR
         (p2.dead = 1 AND
          (p2.death_date = 0 OR
           (((TO_DAYS(p2.death_date) - TO_DAYS(p2.birthday)) / 365)
            >= 65))))
        AND
        (
        /* Twin is suspect */
        (td.future_contact = 'Yes' AND td.suspect = 2) OR
        /* Twin is suspect - Informant is Blessed */
        (td.future_contact = 'Yes' AND td.suspect = 1
                                   AND id.suspect = 1) OR
        /* No twin - Informant is Blessed */
        (ISNULL(td.suspect) AND id.suspect = 1
                            AND id.future_contact = 'Yes') OR
        /* Twin broken off - Informant is Blessed */
        (td.participation = 'Aborted'
         AND id.suspect = 1 AND id.future_contact = 'Yes') OR
        /* Twin broken off - No inform - Have partner */
        (td.participation = 'Aborted' AND ISNULL(id.suspect)
                                      AND p2.dead = 0))
        AND
        l.event = 'Finished'
        /* Get at area code */
        AND SUBSTRING(p1.postal_code, 1, 2) = pg.code
        /* Not already distributed */
        AND (h.nurse IS NULL OR h.nurse=00 OR h.doctor=00)
        /* Has not refused or been aborted */
        AND NOT (h.status = 'Refused' OR h.status = 'Aborted'
        OR h.status = 'Died' OR h.status = 'Other')
ORDER BY
        tvid;

Або ось такий запит, що вибирає товари за критеріями:

SELECT
    products.id,
    products.name,
    price.link,
    price.discount,
    price.click_count,
    price.currency,
    price_currency.name,

    -- default currency is ruble
    (@ori_price:=price.price) AS price,

    -- convertation in dollars
    ROUND(price.price / {$course}, 2) AS dol_price,

    -- select minimal price for product
    (@min_price:=(
                SELECT MIN(price)
                FROM price
                WHERE product_id = products.id
                   && id != price.id
            )
    ) AS min_val,

    -- compare price
    -- " + 1 - 1"
    (@diff:= ROUND(
                    (
                        @max:=GREATEST(@ori_price + 1 - 1, @min_price + 1 - 1)
                        -
                        @min:=LEAST(@ori_price + 1 - 1, @min_price + 1 - 1)
                    ) / @min * 100, 1
                )
    ) AS diff,
    (IF(@ori_price + 1 - 1 <= @min_price + 1 - 1, @diff, -@diff)) AS diff

FROM products
    LEFT JOIN price          ON price.product_id = products.id
    LEFT JOIN price_currency ON price_currency.id = price.currency

WHERE products.archive = 0
ORDER BY products.date_add DESC
 

Переваги NoSQL

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

Ключ-значення

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

Неважко помітити, що це повністю порушує принципи нормалізації, що призводить до ряду недоліків:

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

Денормалізація

Це навмисне додавання всіх необхідних колонок і полів в одну таблицю з метою уникнути об'єднання безлічі таблиць при зверненні до даних. Природно, це призводить до недоліків.

Висновок

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

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


0 комментариев
Сортировка:
Добавить комментарий

IT Новости

Смотреть все