@maxmaxmaxmaxМАКСИМ КЛИМИШИНCTO GVMachines Inc.
Базы данных, python и пять заблуждений о производительности
Сегодня поговорим о
Topic
‣ Python
‣ Почему X не быстрее Y
‣Оптимизации в базах данных
‣Оптимизации и Python
При чем тут python
Базы данных и Python
При чем тут Python
‣ Надо хранить плоские данные
‣ Связанные данные
‣ Графы
‣ Состояния
‣ Следить на консистентностью
‣ Совершать выборки
Наша платформа
При чем тут Python
‣ CouchDB
‣ Solr
‣ Redis
При чем тут Python
‣ Уперлись в скорость создания индекса CouchDB
‣ Постепенно мигрируем с CouchDB в Redis
‣ Активно используем Redis для очередей
‣ Активно используем для Pub/Sub
Наш опыт
Заблуждение №1: База X быстрее базы Y
Алгоритмы
База X быстрее Y
‣ B-tree – O(log n) / most of DBs
‣ Hash – O(1) – O(n) / most of DBs
‣ Log-structured merge-tree – O(log n) / Cassandra
‣ K-D tree – O(log n) – O(n) / Postgres/graph DBs
‣ Boyer–Moore string search algorithm – O(n)
Если коротко, то выше головы не прыгнешь
База X быстрее Y
Тем не менее, полным перебором возможно воспользоваться с дискретной детерминированной системой, состояния которой могут быть легко проанализированы
База X быстрее Y
https://ru.wikipedia.org/wiki/Полный_перебор
Заблуждение №2: Проверенная временем–
значит быстрая
Базовые алгоритмы поиска не менялись.
Новая – значит говно
1961 – QuickSort 1968 – Binary Tree 1972 – B-Tree
Новая – значит говно
Заблуждение №3: В памяти – значит
быстрая
Хочу напомнить, что RAM – это очень круто!
База X быстрее Y
SSD
Все упирается в ограничения:
В памяти – значит быстро
‣ CPU speed
‣ RAM speed
‣ Disk speed
А именно
В памяти – значит быстро
‣ CPU speed – scheduled by OS, depends on LA
‣ RAM speed – fragmentation
‣ Storage speed – fragmentation, latency, depends on type and LA
Серьезный прирост производительности in-memory баз данных происходит потому, что вы убираете целое
измерение при работе с данными
В памяти – значит быстро
Заблуждение №4: Больше железа – все
будет быстрее
Не все так просто
Железо и все дела
‣ Частота одного ядра CPU ограничена сверху
‣ Скорость памяти ограничена типом
‣ Скорость диска ограничена типом
Железо и все дела
Представим, что доступ к одному юниту равен 1ms
Железо и все дела
‣ для извлечения 1000 записей понадобится 1s, нормас
‣ 100K – 100s, долго
‣ 1M – ~16m!!!
Железо и все дела
16 долбанных минут, Карл!
Заблуждение №5: Распределенная – значит быстрая
Серьезный прирост производительности in-memory баз данных происходит потому, что убирается целое измерение
Шардим и лала
Падение производительности распределеных баз данных
происходит потому, что добавляется новое, ненадежное измерение при
работе с данными.
Шардим и лала
Что влечет за собой ряд проблем
Шардим и лала
‣ Consistency or availability
‣ Split-brain scenarios
‣ Conflicts resolution/merging (optimistic replication)
‣ Quorum-based reads/writes
‣ Manual/auto sharding configuration etc.
В частности с репликацией
Шардим и лала
‣ Будут возникать конфликты
‣ Вопрос только в том
1. Когда их разруливать
2. Кто их будет разруливать
Например
Шардим и лала
‣ Amazon Dynamo разруливает на этапе чтения и предоставляет это приложению
‣ А Apache CouchDB на этапе записи и last write win + отложенный механизм разруливания конфликтов
Оптимизации в БД
Как решается вопрос с чтением
Оптимизации
‣ Построение индекса при записи (Postgres, Redis с хранимыми процедурами)
‣ Устаревшие результаты (stale)
‣ Асинхронное создание/предвычисление индекса (вариант stale с внешним индексером)
‣ Шардинг, множественный запрос к нодам шард
Как решается вопрос с записью
Оптимизации
‣ контроль над системным вызовом fsync для процесса БД
‣Отложенное создание индекса до первого чтения (CouchDB)
‣Отложенное создание индекса до (commit явно или по таймауту, Solr)
Оптимизации в Python-е
Как решается вопрос с чтением
Оптимизации
‣ Read on writes (SQLAlchemy)
‣ Кеширование ответов БД
‣ Асинхронные запросы к БД
‣ Асинхронное кеширование
Оптимизации
‣ Py3x – yield from, asyncio
‣ Py2x – gevent, threads pool
‣ For both – solid C implementations
Проблема с чтением в основном связана с внутренней организацией
структур данных Python и множества прослоек по пути между чистым запросом и чистым ответом
Оптимизации
Как решается вопрос с записью
Оптимизации
‣ Read on writes (SQLAlchemy)
‣ Pub/sub и асинхронная запись/очереди
‣ Прямая запись в БД с отложенным/асинхронным созданием индекса (CouchDB)
Спасибо.
Thanks!
@maxmaxmaxmax