Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Максим Поправко. Боль, ужас и без-SQL-ность.

Максим Поправко. Боль, ужас и без-SQL-ность.

Deep Refactoring

December 27, 2016
Tweet

More Decks by Deep Refactoring

Other Decks in Programming

Transcript

  1. БОЛЬ УЖАС И БЕЗSQLНОСТЬ

    View Slide

  2. МИНУТКА БОЯНОВ
    Реляционные (от Oracle до sqlite)
    ● отношения и нормализация
    ● связи отношений и ограничения
    ● ACID
    ● 12* правил Кодда
    ● SQL
    ● 2 БББ*
    MySQL
    Postgre
    Mongo DB
    * Но это не точно

    View Slide

  3. МИНУТКА БОЯНОВ
    Нереляционные (NoSQL)
    ● document (mongodb, orientdb)
    ● графовые (orientdb, neo4j)
    ● key-value (redis, memcache)
    ...тысячи их
    ● JS, Cypher, API любого языка
    ● динамическая схема данных
    ● специфические модели данных
    ○ колонки (без кортежей)
    ○ графы
    ○ иерархические данные
    ○ ключ-значение
    MySQL
    Mongo DB

    View Slide

  4. ЗАЧЕМ NOSQL?
    ● быстрое распределенное чтение
    ● горизонтальное масштабирование
    ● шардинг из коробки
    ● никаких join-ов, агрегаты
    ● eventual consistency достаточно
    ● map/reduce
    ● простые запросы (если это не
    графовая БД, конечно)

    View Slide

  5. ● атрибуты ↔ виды документов
    ● атрибуты ↔ виды атрибутов
    ● атрибуты ↔ тип значения
    ● связи с внешними сущностями
    В простейших запросах в среднем
    ГИТЛЕРИАРД
    join-ов.
    ХРАНИМ ДОКУМЕНТ В RDBMS

    View Slide

  6. ВЫБИРАЕМ ДОКУМЕНТ:
    select *
    from document_info d
    join document_type dt on ..
    join document_type_attribute dta ..
    join document_attribute da ..
    join document_datetime_attribute ddta
    on ddta.id = ...
    … N штук типов семантик
    join organization_documents od on
    od.id_dts = dta.id and …
    … M штук типов ссылок на сущности

    View Slide

  7. MEANWHILE IN MONGO AND NEO4J:
    db.documents.insert ({
    id: ObjectId (“507f1f77bcf86cd799439011”) ,
    title: “Разрешение на использование” ,
    validDue: Date (“11/11/11”) ,
    by: ObjectId (“348f1f7bcf86cd799434893”) ,
    for: [ObjectId (“348f1f7bcf86cd799434893”) ,
    ...
    ]
    ...
    });
    db.documents.find({title: {$regex:
    /^М/}}).sort({title: 1});
    MATCH (grantedBy :Organization :Inspection {name:
    “РЧС”})
    MATCH(issuedFor :Organization :PublicRadio
    {name: “Просто Радио”})
    CREATE
    (issuedFor) - [:PERMIT] ->
    (:Document :Permission {title: “РИ”, ...})
    -[:ISSUED_BY]->(grantedBy)
    MATCH(myPermission :Document) - [:PERMIT] ->
    (justRadio: PublicRadio{name: “Просто Радио”})
    RETURN myPermission.title, myPermission.validDue
    ORDER BY myPermission.validDue

    View Slide

  8. А ЕСЛИ ДАННЫХ ДОХРЕНА?
    RDBMS
    ● мощное железо за все деньги
    ● репликация (читаем с рабов)
    ● шардинг (+денормализация)
    ● горизонтальный шардинг
    Все это непросто и дорого!
    … но будет ли у вас столько данных?
    … нет, 10 миллионов строк это не много.
    NOSQL
    ● просто добавим ноду
    ● суп из семи Hadoop
    … жизнь без наркотиков
    … потеря данных не критична

    View Slide

  9. ЭХ! ЗАЖИВЕМ!*
    * нет.

    View Slide

  10. МИР БЕЗ НАРКОТИКОВ
    A только на уровне документа
    С :( нет транзакций - нет и С
    I read uncommitted, MDW
    D just NO
    ● read concern levels
    ● write concern flags (w, j )
    ● two phase commits (intermediate
    data concern)
    MySQL
    Mongo DB

    View Slide

  11. ● primary асинхронно реплицирует на N
    secondaries
    ● узлы сами решают кто главный
    ● можно получить подтверждение записи
    в логах главного или остальных узлов
    ценой увеличившейся latency
    ● и primary УПАЛ.
    ● если остальные составляют
    большинство, то новый primary - узел с
    наивысшим optime
    ● меньшинство видит, что кворума нет,
    primary теряет чин, запись на него
    невозможна.
    ● GOOD NEWS - NO SPLIT BRAIN!
    ВСЕ ПОШЛО НЕ ТАК

    View Slide

  12. ВСЕ ПОШЛО НЕ ТАК
    ● на главном есть подтвержденные, но не
    реплицированные записи
    ● сеть вернулась и новый secondary
    должен ОТМЕНИТЬ эти операции
    Количество отмененных данных зависит от
    того, что успело реплицироваться на нового
    primary, и это ОЧЕНЬ БОЛЬНО!
    (P.S. данные почти наверняка остались в
    папке rollbacks).
    (P.P.S иногда они просто пропадают и все)

    View Slide

  13. МОЖНО ИСПРАВИТЬ?
    ● сейчас - ДА!
    ● строгие read-write concerns на
    чувствительных данных
    ● двухфазные коммиты

    View Slide

  14. Проблемы динамической схемы данных
    ● атрибуты нетипизированы
    ● byrthday problem
    ● sort по полю, содержащему массивы и
    одиночные значения
    ● нужны автотесты, как и в случае
    динамических ЯП

    View Slide

  15. ПОЛИТЕИЗМ
    ● языки NoSQL разные, часто есть только
    API на common языках
    ● модели доступа к данным разные
    ● нужно искать разработчика, знакомого
    именно с выбранной СУБД

    View Slide

  16. МОЛОДОСТЬ
    ● быстрые изменения фич и API
    ● нет широкого выбора инструментов
    ● bleeding edge крутейших технологий,
    требующих высокой квалификации
    кодеров
    ● нужно искать УМНОГО разработчика,
    знакомого именно с выбранной СУБД
    ● или УЧИТЬСЯ, УЧИТЬСЯ и УЧИТЬСЯ!

    View Slide

  17. КАК ЖИТЬ?
    в этом бардаке?

    View Slide

  18. ● Использовать совместно
    с классическими СУБД
    ● Писать автотесты
    ● Учиться-учиться-учиться!
    ● Использовать гибридные
    решения

    View Slide

  19. P.S. POSTGRESQL 9.3+
    ● JSON, HSTORE
    ● restrictions
    ● where
    ● indexes
    ● hadoop connector
    CREATE TABLE A (
    data JSON
    CONSTRAINT validateId CHECK ((data->>'id')::integer
    >= 1 AND (data->>'id') IS NOT NULL ),
    CONSTRAINT validateName CHECK (length(data->>'name')
    > 0 AND (data->>'name') IS NOT NULL )
    );
    INSERT INTO A(data) VALUES(
    '{
    "id": 1,
    "name": "A",
    "age": 49
    }');
    CREATE UNIQUE INDEX ui_a_id ON a((data->>'id'));

    View Slide

  20. View Slide