Fork me on GitHub
#clojure-russia
<
2017-02-16
>
artemyarulin04:02:27

@bernik вроде тока датомик, есть еще mentat от мозилы сделаные по образу датомика+датаскрипта (https://github.com/mozilla/mentat) но вроде immutability там нету, хотя я не уверен. Если других вариантов нет, а датомик не канает в силу каких то причин то можно сделать самому (ну не весь датомик конечно troll ), либо руками везде пихать триггеры на все таблицы, либо старый (анти)паттерн EAV модель, как например вот тут http://weblogs.sqlteam.com/davidm/articles/12117.aspx

artemyarulin04:02:51

Еще интересный вариант взять какую-нить queue систему (Apache Samza) посередина и пушить все изменения/создания туда как например в этой статье http://dchambers.github.io/articles/databases-are-dead/

artemyarulin04:02:42

Ну и еще отсюда https://news.ycombinator.com/item?id=11689674

I believe you're describing what is typically referred to as an "append only" datastore.
The biggest-name in the game is Google BigQuery

artemyarulin04:02:03

во нашел https://github.com/mirage/irmin, на окамле аж, годно

artemyarulin04:02:57

интересно что почти все статьи про immutable databases написаны авторами которые знают и юзают Clojure. Т.е. с одной стороны датомик да, с другой стороны immutable data structures есть много в каких языках, а такое ощущение что тока кложуристы подсаживаются на это с полной силой 🙂

kishanov05:02:59

в каком-то смысле rethinkdb это поддерживает https://www.rethinkdb.com/docs/changefeeds/ruby/

kishanov05:02:48

там компания вроде как загнулась, но лут с трупа собрали и теперь она доступна в опенсурсе https://www.theregister.co.uk/2017/02/07/rethinkdb_lands_license_to_live/

bernik07:02:52

ну вот как-то так и получается, что все городят какие-то кастыли(триггеры, отдельные таблички versions/history), а искоробочного варианта нет. с другой стороны, в датомике эта hisory-db никак не настраивается, насколько я понимаю. нельзя настроить время жизни этого лога(потому что удалять нельзя) или, хотя бы, какой-то механизм типа git rebase, который бы в общем случае выглядел бы как reduce по истории

niquola08:02:15

Мы в postgresql только вставляем - по две таблички всех сущностей делаем

niquola08:02:52

Как раз полный контроль над историей получается, но не из коробки.

niquola08:02:29

Интересно что в статье по дизайну постгреса от 80 года был пункт про сохранение историчных данных и запросы над ними - из этого остался только mvcc

niquola08:02:32

Те если в PG выключить вакуум - оно и получится ;)

niquola08:02:59

Можно наверно упороться и пропатчить PG для этого

niquola09:02:52

У нас что-то типа такого - http://clarkdave.net/2015/02/historical-records-with-postgresql-and-temporal-tables-and-sql-2011/, но без тригеров

dottedmag10:02:48

@bernik Вот удаление старых данных: http://docs.datomic.com/excision.html

dottedmag10:02:31

rebase не нужен. точнее, rebase вреден. зачем портить историю?

misha10:02:06

вместо эксижена рекомендовали менять базу, как rolling log file appender. что бы окно хистори было сколько-то месяцев/лет крайних

misha10:02:24

типа эксижн - на случай судовых требований и тд. и он не удаляет-удаляет, а что-то за собой оставляет, tombstone какой-то

misha10:02:06

с учетом этого всего и лимита датомов, есть смысл данные делить на несколько баз сразу, чтобы "индивидуально" принимать решения и иметь дело с ростом хистори

misha10:02:23

типа юзеров - в одну, заказы - в другую, аналитику пользования приложухой - в третью.

bernik10:02:17

@dottedmag такой rebase скорей для оптимизаций вида истории. например сделать squash мелких изменений в одно большое, чтобы не делать тоже самое каждый раз когда захочется посмотреть историю изменения документа

andmed12:02:06

для чего нужны персистентные базы, какую задачу решают? ведение истории изменения поля?

andmed12:02:34

скажем, я пишу сервис отслуживающий фоловеров. т.е. нужна история изменений сета с айдишниками. Что бы я сделал в SQL: таблица 1: колонки user_id, timestamp, follower_id (+ фоловер подписался, - отписался) таблица 2: хранит последнее известное состояние (список id фоловеров). чтобы показать историю, беру текущий стейт из второй таблицы и отматываю до нужного таймстампа по первой. итого два селекта

andmed12:02:38

это об этом?

misha12:02:42

@andmed тебе презентации Хикки про бд смотреть надо - там убедительно

andmed12:02:05

харизма у него есть, согласен

misha12:02:11

не в харизме дело

misha12:02:14

в джаве ты тоже можешь руками "атомы" менеджить между тредами без канкаренси проблем, только за###шься

andmed12:02:09

т.е. пойнт в изоляции, не в хранении бэклога?

misha12:02:28

датомик, как и кложа - по пунктам - не очень убедительно звучит, но если как целый продукт расматривать - очень круто.

misha12:02:02

потому посмотри презентации - там комплексно описано, чем датомик четкий: запросы на клиенте, кеш на клиенте, бесплатный скейлинг на чтение, запросы по истории, любой сторадж и тд

misha12:02:50

но персистентные бд вроде решают задачу хранения истории, да

andmed12:02:39

ок... ну значит я неоилятор, блин, мне написать свой велосипед как-то проще.. может задач не было подходящих

andmed12:02:01

можно мой случай изменить так, чтобы был смысл смотреть на датомик?

misha12:02:07

ну и канкаренси решают. типа консистентный результат запроса по бд на момент времени t

misha12:02:33

датомик имеет смыл смотреть для общего развития расширения сознания как минимум

artemyarulin12:02:32

@misha а ты его юзаешь в итоге где?

artemyarulin12:02:44

ну кроме как поиграться и забыть я имею ввиду

andmed12:02:40

не вот мне правда интересно понять смысл, юзкейс так сказать

misha12:02:01

там же где и реакт нейтив, но последние полгода+ я в мобилочке колупаюсь, бекенд не трогал совсем, но синк датаскрипта с датомиком у меня черновой нахачен уже

misha12:02:33

@andmed какой юзкейс у кложи?

andmed12:02:35

речь о персистентой бд, это более экзотичная вещь чем кложа. не?

misha12:02:08

у меня юзкейс: на мобиле датаскрипт, на сервере датомик, синхронизация - 2 страницы кода. сохранение кложа-типов при записи/чтении, запросы по истории, даталог и пулл-паттерны динамически можно собирать (а не бл##ские sql строки плюсовать)

misha12:02:53

я спросил, чтобы показать, что любой однофразовый ответ - неплоный

andmed12:02:39

ну ты уводишь на sql я просто показал как я бы решал задачу бэклога если я правильно понимаю смысл персистентной базы. насчет sql btw google с тобой не согласен http://datascienceassn.org/sites/default/files/F1%20A%20Distributed%20SQL%20Database%20That%20Scales.pdf

andmed12:02:51

но речь о персистентной базе

niquola12:02:57

datomic по моему - это гибрид orm и базы данных. Как раз персистентные аппендонли DB не уникальны - в смысле что mvcc часто используются для изоляции транзакций, и там оперируют снэншотом базы данных

andmed12:02:05

ну да. бд собаку съели на изоляции

andmed12:02:30

потому и спросил

niquola12:02:53

datomic интересная композиция - append only, search and indexes on pear , triple store ;)

andmed12:02:20

хмммм... tripple store

misha12:02:22

@andmed уже бы посмотрел половину презентации, пока тут наводящие вопросы задаешь opieop

andmed12:02:01

почему наводящие? я же не утверждаю что персистентные бд не нужны

niquola12:02:52

Я говорил с чувакам из postgrepro - они скептичны насчет эффективного триплстора

niquola12:02:16

Меня расстроило понятие - most selective clause

niquola12:02:44

Это значит, что планировщика и статистики нет в datomic

niquola12:02:52

Или есть?

niquola12:02:17

Те нифига оно не декларативное, раз от порядка зависит

misha12:02:01

(единственный упрек sql из сообщений выше - конкатенация строк для динамического построения запросов)

misha12:02:38

@nicola скорость выполнения не декларативная kappa

niquola12:02:45

Ну она достаточно важна, иначе это игрушка, которая начнёт тупить на миллионах записей

niquola12:02:00

На на порядки может быть разница

niquola12:02:39

При этом трипл обрекает на большое количество join и на более менее сложных запросах хьюманбрэйн уже не справится

niquola12:02:50

- комбинаторный взрыв планов выполнения

misha12:02:32

кажется мне, что ты рассматриваешь характеристику "трипл стор" вне контекста конкретно датомика

niquola12:02:30

А в чем разница?

misha12:02:31

но фактов у меня никаких нет )

misha12:02:03

ну там же куча слоёв кеша у них и тд, те же персистентные данные, которые может там чота ускоряют, и тд

misha12:02:29

вообще, есть же музик дб демочковая - там можно потестить что как быстро работает

niquola12:02:34

Попробуй сделать 10 join 1M записей пусть и в памяти, пусть и по индексам

misha12:02:03

+ запросы же на клиенте - берешь бокс потолще и задаёшь такие вопросы там

andmed12:02:36

персистентные данные, которые может там чота ускоряют правда?

misha12:02:43

у меня ни живого апликейшена нет, ни такого объема данных, ни сорцов датомика, так что хз

misha12:02:05

@andmed что именно правда?)

niquola12:02:14

Тут вопрос откуда исполнение начинать - и планировщик может найти на порядки более эффективный путь

niquola12:02:29

С использованием статистики

misha12:02:58

реакт вон ускорили, где сравнивали хеши объектов. я баз данных не писал, и деталей алгоритмов не знаю, может там есть чо ускорить кешом и персистентностью

niquola12:02:16

В общем чтоб считаться полноценной дб у датомик кое чего не хватает

misha12:02:11

@andmed ты-то думаешь, что пошутил kappa

andmed12:02:46

да нет, я знаю что датомик "паразитирует" на хранилище))

misha12:02:52

как раз про время отрывок

misha13:02:47

@nicola слушай, а ведь можно считать сколько в базе записей конкретного атрибута, и в зависимости от этого менять местами стейтменты в запросе

niquola13:02:10

это и есть первые шаги планировщика

niquola13:02:23

еще нужно заводить статистику на значения

misha13:02:28

можно нахачить )

niquola13:02:59

оценивать селективность условия 🙂

misha13:02:56

So that is what we've decided to do (as of 0.8.3372). Now, in the case of the second query, we will run it in the order you specified and this will run as fast as the first query. If you manually write it in the second order, it will run slowly. But, rather than wondering what is happening in a black box and trying black art things like the [(= ?n 4)] clause, you can simply try another order. 

misha13:02:13

сейчас девелопер - планировщик

misha13:02:23

я может сопляк еще, но мне кажется, что это мелочи всё (руками скорость квери проверять) в сравнении с полезняком датомика

niquola13:02:21

Пока все уместиться в памяти и выборки будут селективными - он будет работать

misha13:02:57

чем это отличается от невлезшего в память sql запроса (который с планировшиком)?

misha13:02:42

тем, что тут лёг 1 пир, а там - вся бд opieop

niquola13:02:55

Тем что PG за секунды лопатит запросы с миллионами строчек и без индексов

niquola13:02:17

Вобщем надо побенчмакркать

misha13:02:47

т.е. утверждаешь, что у PG всегда "влезет"?

niquola13:02:43

он mmap делает - не обязательно в память влезать

misha13:02:57

а сколько в вашем (мед?) продукте разных запросов? и сколько из них таких тяжелых

niquola13:02:05

ну просядешь на порядок

niquola13:02:12

а в датомике на несколько

niquola13:02:38

если про ehr - сотни

niquola13:02:13

несколько десятков - тяжелые

niquola13:02:33

но я боюсь что в датомике они бы на пол дня зависли

niquola13:02:53

нужно проверять

misha13:02:55

отдебаженые? в смысле "с хорошей перестановкой уже"

niquola13:02:26

ты имеешь ввиду оптимизированные

misha13:02:36

that's the word opieop

niquola13:02:52

проблема в том, что оптимизация может от данных зависеть

niquola13:02:12

у одного пациента 10 лаб резалтов, у другого 1000

niquola13:02:22

у некоторых 10К

niquola13:02:34

и у тебя нету one fit all запроса

misha13:02:55

а разве так часто бывает, что сегодня abc запрос в 10 раз медленнее, чем acb, а завтра наоборот, а послезавтра снова?

niquola13:02:26

это зависит от распределения данных

niquola13:02:42

представь тебе нужно сджойнить три таблицы

niquola13:02:52

на каждую из них наложены условия

niquola13:02:28

например для одного пациента оценка выдаст t1 - 100 rows, t2 - 100000 rows, t3 - 500rows

niquola13:02:41

и ты начнешь с t1

niquola13:02:00

а у другого наоборот t1 - 100000, t2 - 1, t3 - 2

niquola13:02:13

и тут бы хотелось с t2 начать

niquola13:02:44

и приехали - на первом все летает, на втором висит

misha13:02:17

ну вот я перебираю пару доменов, пытаясь найти "такие 3 таблицы"

niquola13:02:03

ну если у тебя в основном крудик и выборки на одной таблице - то все ок

misha13:02:09

в бд метаданных для кино в сони такого нет, даже с учетом того, что там пере-импортировались данные для фильма сотни раз не перетирая, а аппенд онли

misha13:02:48

т.е. если там вспухает таблица какая-то - она скорее t3 всегда, а чтоб вспухла t1 - таких бизнес запросов нет просто

misha13:02:54

даже типа "все метаданные (t3-tn) для всех видео (t2) парамаунта (t1)"

niquola13:02:29

в канале datomic вроде начали отвечать

misha13:02:49

stuartsierra [3:41 PM] 
<@U0514TE0F> It means that you are responsible for monitoring and optimizing the performance of your queries based on your data. Future releases of Datomic may be bundled with tools to assist in this analysis, but they are not part of the current release.

misha13:02:30

мне всё еще кажется, что твой пример надуманный можно acceptably заоптимизировать раз, и через пол года перепроверить актуальна ли оптимизация (помножить на пару десятков тяжелых кверей в твоём проекте)

niquola13:02:20

у тебя запрос зависит от параметров - так?

niquola13:02:38

в зависимости от параметров - вернутся разные данные

misha13:02:04

ну я понимаю о чем ты. всегда же можно оценить самый неудачный случай

niquola13:02:12

и тут ситуация что ты не можешь написать один запрос для разных параметров и данных

niquola13:02:46

те тут принципиальная зависимость - эффективности запоса от данных

misha13:02:50

можешь, просто он будет не максимально медленным и не максимально быстрым

niquola13:02:52

которой нет в datalog

misha13:02:23

но будет acceptable

niquola13:02:29

и раз в месяц все твои пиры будут виснуть на каком нибудь ворст кейсе

misha13:02:51

там жеж кеш! opieop

niquola13:02:53

либо ты в коде начнешь изобретать планировщик

niquola13:02:10

кэш не поможет при джойне 10 милионных коллекций

misha13:02:13

для начала хочу, чтобы у меня появились "все мои пиры" 🙂

niquola13:02:52

10 * 1М nested loop - будет занимать несколько секунд а то и десятков

misha13:02:57

а что за запрос такой, в котором надо 10м джойнить? надо ж пофильтровать 10м сначала

niquola13:02:59

даже в памяти

niquola13:02:29

в случае с datomic это все может на одной сущности произойти

misha13:02:39

или пагинацию там, если у тебя слишком больной пациент

misha13:02:43

кажется, это решается разовой оптимизацией и периодической перепроверкой. доказать не могу

dottedmag18:02:59

Ну, да. Workload более-менее известен, а если меняется - всё равно надо заново смотреть, как что происходит.

dottedmag18:02:27

@misha Даже периодически проверять на надо, а просто впихнуть инструментирование и глядеть, если время запросов начинает вылезать за лимит.

misha18:02:15

@dottedmag я ~ о том же

jetmind19:02:12

может как-то так? приятнее читается

(let [offset (cells-offset coord (-> state :draw :brush))]
  (update state :field (partial merge offset)))

kgofhedgehogs19:02:42

Да. Мне нравится. Спасибо Никак не могу привыкнуть подпихивать let для читабельности

kgofhedgehogs19:02:39

get-in без дефолтного значения лучше заменять на ->? (если ключи это кворды)

jetmind19:02:47

не скажу лучше или нет — вкусовщина, но мне больше нравится стрелочка

jetmind19:02:00

плюс не надо создавать лишний вектор)

alexander_mihailov19:02:34

а если еще и шрифты с лигатурами, то стрелочка красивше.

jetmind19:02:02

точно!)

kgofhedgehogs19:02:03

А. Так это еще от шрифта зависит. Думал, от темы Всё. Теперь красота

larhat20:02:27

@kgofhedgehogs select-keys + что-то ещё, типа (select-keys s (keep (fn [[k v]] (when v k)) (d :show))) {:framerate 15, :generation 130}

kgofhedgehogs20:02:33

Спасибо

kgofhedgehogs21:02:54

Как лучше? #(update % 0 name) или (fn [[k v]] [(name k) v])

kgofhedgehogs21:02:56

Входит типа MapEntry, где ключ это кворд, а выходит пара ключ значение, где ключ это String

kgofhedgehogs21:02:15

(select-keys s (keys (filter val (d :show))))

dottedmag22:02:44

@kgofhedgehogs Второе понятнее