• Чи може PostgreSQL з його JSONB замінити MongoDB

    Окрім того, навіть на такому об’ємі можна спростувати деякі міфи, які я чув навіть від досвідчених розробників: «GIN індекс в PostgreSQL набагато швидший за звичайні індекси», «MongoDB завжди більш ефективна для роботи з документами, ніж JSONB в PostgreSQL», «MongoDB швидше виконує агрегації» і т.д.

    Ви робите узагальнені висновки на дуже простій колекції/таблиці. Чому ви не розглядаєте роботу/пошук з вкладеними документами, масивами документів і т.п.? Якщо використовувати плоскі документи, то навіщо вам JSON?

    Підтримав: Denys
  • Чи може PostgreSQL з його JSONB замінити MongoDB

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

    Чому ви вирішили, що пошук/сортування ведеться на основі індексів? Ви дивились плани ваших запитів? Для розуміння було б корисно привести їх у аналізу результатів. Більш того, має значення розподіл індексованих даних. Наприклад, є поле, яке має тільки 2 значення, у колекції/таблиці дані поля розподілені 50/50, у такому випадку індексування цього поля не додасть якогось перфоменсу. Я розумію, якщо є бажання погратися з індексами, але навіщо для цього робити бенчмарк? Достатньо буде зручний вам клієнт до БД (mongodb або postgresql) і плани ваших запитів.

    P.S. у мене є досвід роботи з колекцією mongodb, розмір якої більше 2 млрд документів, в залежності від результату, пошук виконувався мілісекунди/десятки мілісекунд. Авжеж, були і проблемні пошуки, але це більш стосувалося обробки на стороні клієнта, а не mongodb. Тому і виникає багато запитань до 11 млн документів і результатів вашого бенчмарку.

    P.P.S. з моєї точки зору для 11 млн простих документів/рядків не має значення, яку БД використовувати (mongodb, postgresql, mysql ..., JSON/regular tables), вибір буде залежати від кошторису використання і експертизи команди підтримки. Але для більш великих даних, я б вибрав щось надійне і перевірене — mongodb shard cluster, а не postgres citus.

  • Чи може PostgreSQL з його JSONB замінити MongoDB

    Стаття гарна, але є наступні питання до тестів:

    * Не зрозуміло, яка була структура даних з індексами, наприклад, SalesTable.json для mongodb можно було б замінити або описати повноцінну схему валідації з індексами. Теж саме можно було б зробити/описати для SQL DBs.

    * По індексам не розглянути різні цікаві кейси:
    * індекс по полям з масиву
    * індекс з NULL значеннями
    * індекс з відсутніми полями (для mongodb можна використовувати sparse індекс)

    * Не зрозуміло, які використовувалися вибірки. Наприклад, для префоменсу mongodb не має сенсу використовувати декілька роздільних індексів у одному запиті. Тобто не зрозуміло (або зрозуміло), чому така різниця у запитах MongoDB Composite Idx і MongoDB Separate Idxs.

    Дивно, але окремі індекси в PostgreSQL працюють набагато гірше, ніж окремі індекси в MongoDB, незважаючи на згадану раніше оптимізацію сканування індексу (bitmap scan). MongoDB використовує індекс TimePeriod для сканування всіх відповідних записів, які вже розміщені в правильному порядку, а потім фільтрує кожен відсканований рядок за країною, доки не буде знайдено достатньо результатів для сторінки.

    Результат mongodb може бути значно гірше, все залежить від об’єму даних індексу.

    * Як я зрозумів, у деяких запитів використовується сортування. У mongodb я б не використовував фільтрацію і сортування окремими індексами. А якщо у вас невеликий результат вибірки, я б зовсім відмовився від сортування на стороні mongodb.

    * Із статті не зрозуміло, як вибираються данні на клієнтської стороні. Наприклад, mongodb використовує курсор з fetch параметром. Якщо у вас велика вибірка, то вам потрібно вичитати усі данні (буде декілька запитів до mongodb).

    * У даному аналізі були приведені результати запитів з сторони dotnet клієнта. Це цікаво, але хотілось б зрозуміти, а що там на стороні DB — CPU, Memory, IOPS, час виконання запитів на стороні DB. Тобто, якщо вибирати DB, то хотілось би більше результатів з DB, а не клієнта (скільки там часу займає серіалізація/десеріалізаця, використовується серіалізація/десеріалізаця драйвера/провайдера або щось своє, скільки часу пішло на GC т.п.).

    * 11 мільйонів рядків — це не зрозумілий об’єм даних, хотілось б розмір на диску. Більш того, я не бачу сенсу використовувати mongodb для такого об’єму даних. Хотілось б подивитись, як будуть працювати mongodb vs postgresql хоча б для 500 млн рядків.

    * Не зовсім зрозуміло, чи враховують JIT компіляцію результати бенчмарку (я не знаю, які є оптимізації зараз у дотнеті, але для джави це має значення). Не зрозуміло, чому було вибрано 1000 запитів на 1 поток, а не, наприклад 10000 і як це вплине не результати.

    Мій висновок — для вибору DB немає сенсу використовувати загальні тести з мікробенчмарку, тому що багато чого залежить від структури даних, об’єму, сценаріїв використання, інструментів експлуатації, подальшого розвитку системи. Тому кожна команда/компанія повинна проводити свій аналіз, свої внутрішні тести, включно з довгостроковим навантаженням (наприклад, для шард кластеру mongodb операція «move chunk» може бути болячою у час пік навантаження).

    Підтримав: Denys
  • Чи може PostgreSQL з його JSONB замінити MongoDB

    Деякі називають шардування та вбудований повнотекстовий пошук перевагами MongoDB порівняно з традиційними реляційними базами даних...
    ... шардування може бути реалізовано за допомогою розширення Citus

    Питання до автора — скількома терабайт даними ви оперували у вашому тестовому шард кластері? У вас були довгострокові навантажувальні тести шард кластера?

    Підтримав: Denys
  • П’ять причин, з яких вам варто використати Kotlin

    Це означає, що після котліна перейдеш до джави :) Повір на слово ;)

    Підтримав: Віталій Мартиник
  • ScopedValue vs ThreadLocal. Новий крок в еволюції Java

    Если честно, то перечисленные проблемы ThreadLocal не такие уж и проблемы:

    Mutability.

    Вот простой код неизменяемого ThreadLocal (за искоючением remove):

    final class ImmutableThreadLocal<T>  {
        private final ThreadLocal<T> threadLocal;
    
        public ImmutableThreadLocal(Supplier<T> initValue) {
            if (initValue == null) {
                throw new IllegalArgumentException("initValue is null");
            }
            threadLocal = ThreadLocal.withInitial(initValue);
        }
    
        public T get() {
            return threadLocal.get();
        }
    
        public Optional<T> getOpn() {
            return Optional.ofNullable(get());
        }
    
        public void remove() {
            threadLocal.remove();
        }
    }
    
    Недоступність для дочірніх потоків.

    Вообще не проблема, используйте InheritableThreadLocal (Since: 1.2) и ваши дочерние потоки получат доступ к вашим переменным из родительского потока. Вот только эта фича за очень редким исключением кем-либо используется. У вас оочень плохой пример использования одной транзации в дочерних потоках — это может приветси к оочень серьезным проблемам.

    Необхідність явного очищення встановлених даних.

    Все зависит от сценария использования. Вот вы ориентируетесь на спринг, как на эталон качества, а их реализация совсем далека от качества — использование транзакций в виде аннотаций оочень плохой подход. Ну и вот вам простой пример очистки реусрсов:

    class ImmutableThreadLocalResource<T> implements AutoCloseable {
        private final ThreadLocal<T> threadLocal;
        private final Thread initThread;
        private volatile boolean closed;
    
        public ImmutableThreadLocalResource(T value) {
            if (value == null) {
                throw new IllegalArgumentException("value is null");
            }
            threadLocal = new ThreadLocal<>();
            threadLocal.set(value);
            initThread = Thread.currentThread();
        }
    
        public boolean isPresent() {
            return !closed && initThread == Thread.currentThread();
        }
    
        public boolean isClosed() {
            return closed;
        }
    
        public T get() {
            final var value = threadLocal.get();
            if (closed) {
                throw new IllegalStateException(String.format("%s is closed", ImmutableThreadLocalResource.class.getSimpleName()));
            }
            if (!isPresent()) {
                throw new IllegalStateException("attempt to get from non-initial thread");
            }
            return value;
        }
    
        public Optional<T> getOpn() {
            return Optional.ofNullable(get());
        }
    
        @Override
        public void close() throws Exception {
            if (!closed) {
                synchronized (this) {
                    if (!closed) {
                        if (!isPresent()) {
                            throw new IllegalStateException("attempt to close from non-initial thread");
                        }
                        try {
                            final var value = get();
                            if (value instanceof AutoCloseable) {
                                ((AutoCloseable) value).close();
                            }
                        } finally {
                            threadLocal.remove();
                            closed = true;
                        }
                    }
                }
            }
        }
    }
    
    ...
    
    try (final var threadLocalTx = new ImmutableThreadLocalResource<MyTx>(new MyTx(...))) {
        ...
    }
    

    Основная прблема ThreadLocal в том, что вы не можете использовать одно значение в нескольких потоках по определению. Например, вы используете неблокирующий HTTP сервер (например, Undertow), котрый выделяет небольшое кол. потоков на обработку HTTP запроса, при этом обработка одного запроса может выполняться в нескольки потоках, если вы обращаетесь к внешним ресурсам — файлы, сеть (БД, внешний сервис ...). В этом случаи использование ThreadLocal приведет к серьезным проблемам, вот поэтому многие программисты не любят ThreadLocal, вот поэтому спринг со своими транзакциями и другими подходами, использующие ThreadLocal, обнулились и им пришлось реализовать WebFlux.

    Так вот, из статьи не понятно, как же ScopedValue поможет нам решить основную проблему ThreadLocal — использование одного значения в нескольких потоках? Из JEP 428: Structured Concurrency (Incubator)

    Simplify multithreaded programming by introducing an API for structured concurrency. Structured concurrency treats multiple tasks running in different threads as a single unit of work, thereby streamlining error handling and cancellation, improving reliability, and enhancing observability. This is an incubating API.

    Т.е. API позволяет выполнять одну «работу» (UnitOfWork) в нескольких потоках. Например, обработка одного HTTP запроса в нескольких потоках, которые используют одну транзакцию, а по завершению обработки («работы»), транзакция закрывается (атоматом? возможность добавить специализированный код по закрытию? и т.д.).

  • Токсичний код рев’ю

    Во первых, смысл код-ревью джуниора заключается в том, что бы джуниор поднял свой уровень, поэтому как-то удивляет, что джуниор делает подобное ревью. Во вторых, любые замечания по стилю кода должны приниматься только после добавления в проект документа «Code Style», если нет документа или замечание по стилю (включая имена) ни как не связано с документом, то можно (а по мне, так НУЖНО) мягко послать ревьювера на создание/расширение документа. Ну и по всем замечаниям надо задавать вопросы — как это улучшит читабельность, производительность и т.п. Вполне возможно, что он не джуниор и замечания имеют место быть, но без подробных пояснений вы не поймете, зачем все эти изменения.

  • «Юзер платить не за красивий код, а за вирішення його проблеми», або Чому бізнесорієнтованість розробника важлива

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

  • «Юзер платить не за красивий код, а за вирішення його проблеми», або Чому бізнесорієнтованість розробника важлива

    Почему редко получается? Вы судите об этом на основе 0.001% удачных стартапов, которые решили поделиться «формулой» своего успеха?

    Підтримав: Roman Pavlyuk
  • «Юзер платить не за красивий код, а за вирішення його проблеми», або Чому бізнесорієнтованість розробника важлива

    Все относительно. Рассмотрим вот такой кейс. Вы, стартап, выкатываете на рынок полурабочий продукт. В течении полугода вы постоянно выкатываете новые полурабочие фичи, с задержками исправляя старые баги. Вроде как клиенты растут — ваш продукт на текущем рынке не имеет конкурентов. Но вот тут, откуда не возьмись, через те же пол года появляется первый конкурент — имеет более удобный сервис и на порядок меньше багов. И новые фичи у него более чем рабочие. Через еще пол года конкурент вас полностью выкидывает с рынка (вам же как бы надо больше фичей, что бы конкурента задавить). К чему этот кейс? К тому, что срать на баги надо с умом, особенно если у вас есть или может появиться конкурент :). Так что надо искать баланс между рынком и качеством.

    Підтримали: Dmytro Lapshyn, Roman Pavlyuk
  • «Юзер платить не за красивий код, а за вирішення його проблеми», або Чому бізнесорієнтованість розробника важлива

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

  • «Юзер платить не за красивий код, а за вирішення його проблеми», або Чому бізнесорієнтованість розробника важлива

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

    1. Назва «Юзер платить не за красивий код, а за вирішення його проблеми» не дуже бізнес-орієнтована :). Користувач платить за зрозумілий, зручний та якісний сервіс. Йому начхати на код і він не повинен думати про якісь проблеми, користуючись вашим сервісом (це стосується не тільки цифрової частини вашого сервісу).

    2. Якщо ваша продуктова компанія надає тільки цифровий сервіс (технологічна продуктова компанія), то основні затрати компанії будуть на розробку (у сервісу може бути багато систем на бакенді, наприклад, мікросервісна архітектура, багато інтерфейсів, таких як мобільні, веб і т.д.), підтримку сервісу (баг фікс, зміна вже існуючих фічів, розробка нових та вбудування їх у ваш сервіс), підтримку інфраструктури та на саму інфраструктуру. Якщо дивитися з точки зору розробників, то вони повинні намагатися знайти оптимальну рівновагу між продуктивністю розроблених систем, витратами на інфраструктуру та часом розробки. Успішність цій рівноваги залежить, як мінімум, від двох факторів — процесс розробки і архітектура вашого сервісу (який може включати багато розроблювальних систем). Тобто, якщо ви (ваша компанія) забиває на архітектуру, то бог вам у поміч, тому що компанії буде нема на кого сподіватися коли почнеться... А воно може початися зі зростом користувачів та компанії :). Тобто я б не радив користуватися вашими порадами про нехтуванням архітектури чи DDD (якщо у вас складний домен). І зовсім не радив нехтувати принципами SOLID у будь якій ситуації при використанні об’єктно-орієнтованої платформи. SOLID ні як не гальмує розробку. Якщо ви не користуєтесь чи не вмієте користуватися SOLID принципами, наприклад, у джаві, то це тільки каже про ваш рівень розробника.

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

    4. Якщо ваша розробка, а не тестування, орієнтована на data-driven, тобто, розробка більш менш тупого редактора БД чи перенесення даних з точки А у точку Б, то вам зовсім не потрібно перейматися бізнес-орієнтованістю. Вам потрібно перейматися тільки тим, щоб усі ваші дані були вчасно на місці :).

    5. З порад автора для бізнес-орієнтованої розробки, як мінімум, я б виключив прокачування навичок стратегічного мислення :). Для розробки це зовсім не потрібно. Більшість компаній не має спеціалістів зі стратегічним мисленням. Більш того, більшість держав не має спеціалістів зі стратегічним мисленням, наприклад, держава України (я не про всіх громадян). Якщо ж вам цікаве стратегічне мислення, то почніть, наприклад, з банди чотирьох — Сергій Дацюк, Юрій Чудновський, Володимир Нікітін і Тарас Бебешко. Можливо вам це зайде :).

    Підтримали: Andrii Fursenko, Pavlo Soia
  • З консерваторії в IT. Як 24-річна харківʼянка опанувала Angular та поміняла гітару на компʼютерний код

  • Справжні вбивці С++

    Скиньте ссылку, где я могу получить ответ на

    и как юзать вот этот go без gc?

    Ну а если нельзя Go юзать без GC и GC в Go оптимизирован только под пропускную способность, то выходит, что на Go имеет смысл реализовывать задачи с большой пропускной способностью (и плевать на процессор и память). При этом реализация GC в Go не уплотняет память, что может привести к ее нехватки. Отсюда вывод — Go относительно узкоспециализированный язык/платформа. Да, есть много задач под его специализацию (например, апишечек на порядки больше, чем софта под мед. оборудование). Но ни как нельзя утверждать, что Go может заменить распространенный (пусть и легаси) язык/платформу с очень широким назначением. Rust? Может быть. Я не знаю. Но Go точно не вариант.

  • Справжні вбивці С++

    Вообще то я пытаюсь понять

    и как юзать вот этот go без gc?

    Ссылочка на мой вопрос. А вот это ссылка на корневой комментарий.

  • Справжні вбивці С++

    В этой ветке идет обсуждение, что c++ можно без проблем заменить языком go. Тогда возникает вопрос, зачем вы пишите о rust или си, если есть go? Или это такие странные аргументы за go, что он может без проблем заменить c++ при помощи rust :)?

  • Справжні вбивці С++

    Чего-чего? Тут требуется разъяснительная бригада.

    Есть огромное количество успешных проектов на QT. Например, приложения, написанные на QT, более кроссплатформенные, чем написанные на .net (включая mono).

    Откуда вы знаете, на чём и как они сейчас пишут? MS уже давно заявляла, что .Net у них флагманская платформа, под которую они будут писать всё, включая компоненты ОС.

    Сам майкрософт писал об этом. Он подумывал о переходе на rust. Замете, не на go. Надеюсь, вы понимаете, что ОС — это не только десктоп оболочка. Если так говорить, то линукс то же написан на с++ (смотрим, что там в KDE).

    Тут без разницы, на чём их писать. OrientDB например вообще переписан с C++ на java. Что-то ещё под ноду написано, поскольку там всё равно js.

    Вот вы сами говорите, что куча языков используется для написания БД. Хотя бы одно популярное БД есть на go? Или, хотя бы, не популярное.

    Вот как раз и пишутся на Go, это целевой сегмент разработки на Go. Причём зачастую код переписывается с C++ где нет GC, на Go где есть GC. А всё почему? Потому, что архитектурные решения имеют первичное значение, а код C/C++ занимает сегодня нишу оптимизационных решений.

    Приведите, хотя бы одну подобную систему, которая хотя бы на 30% была написана на go. Это не тролинг, мне реально интересно, как же оно все работает с gc от go.

    P.S. могу ошибаться, но, насколько я знаю, OrientDB изначально был написан на java.

    Підтримав: Roman Pavlyuk
  • Справжні вбивці С++

    «перечислить несколько „конкретных решений“, которые можно применять в Rust»

    Я немного устал писать о том, что сейчас идет обсуждение — как go может заменить с++. В можете посоветовать хотя бы одну книгу по управлению памятью в go, из которой будет понятно, как он может полностью заменить c++?

    з.і.
    dou.ua/...​rums/topic/38670/#2432930

    Я думал, что из контекста понятно, что мы обсуждаем с++, а не все языки мира.

  • Справжні вбивці С++

    Потому что с моей точки зрения управление памятью в C++ мягко говоря хромает

    Я понимаю вас. Но мне не понятно, как прочтение книги от Джона Гьенгсета поможет schwarzlichtbezirk разобраться в управлении памятью в с++? В книге от Джеффа Элджера предложены различные концепты, от счетчика ссылок, до gc. Обсуждать rust я не хочу, т.к. у меня нет такой экспертизы в rust, что бы провести глубокое сравнение c++ и rust. Если бы эта ветка обсуждения была бы о rust vs c++, я бы еще понял. Но мы здесь обсуждаем, как go может полностью заменить c++. А может go может заменить rust? И не имеет значение, что rust появился позже go :). У вас есть какие-либо аргументы за go в этих вопросах?

  • Справжні вбивці С++

    Где вы видели, что бы я писал, что c++ — крутой супер-пупер язык? В этой ветке идет сравнение «спуер-пупер» языка go, который без проблем может заменить c++. Я пытаюсь понять, как он может заменить с++? Может быть вы видите, как go может заменить c++, например, в ядре винды или в проектах реального времени или ...?

← Сtrl 123456...20 Ctrl →