Замена EAV на JSONB в PostgreSQL

Автор оригинала: Jeroen Coussement
  • Перевод
TL; DR: JSONB может значительно упростить разработку схемы БД без ущерба производительности в запросах.

Введение


Приведем классический пример, наверное, одного из старейших вариантов использования в мире реляционных БД (база данных): у нас есть сущность, и необходимо сохранить определенные свойства (атрибуты) этой сущности. Но не все экземпляры могут имеют одинаковый набор свойств, к тому же в будущем, возможное добавление ещё свойств.

Самый простой путь решения этой проблемы – это создание столбца в таблице БД для каждого значение свойства, и просто заполнять те, которые нужны для определенного экземпляра сущности. Отлично! Проблема решена… до того момента, пока ваша таблица не содержит миллионы записей и у вас не возникнет необходимость добавить новую запись.

Рассмотрим паттерн EAV (Entity-Attribute-Value), он встречается достаточно часто. Одна таблица содержит сущности (записи), другая таблица содержит имена свойств (атрибутов), а третья таблица связывает сущности с их атрибутами и содержит значение этих атрибутов для текущей сущности. Это дает вам возможность иметь разные наборы свойств для разных объектов, а также добавлять свойства “на лету”, не изменяя структуры БД.

Тем не менее, я бы не писал эту заметку, если бы не было недостатков в подходе с использованием EVA. Так, например, для получения одной или нескольких сущностей, которые имеют по 1 атрибуту требуется 2 join'а (объединения) в запросе: первый – объединение с таблицей атрибутов, второй – объединение с таблицей значений. Если сущность имеют 2 атрибуты, то нужно уже 4 join'а! Кроме того, все атрибуты обычно хранятся в виде строк, что приводит к приведению типов, как для результата, так и для условия WHERE. Если вы пишете много запросов, то это достаточно расточительно, с точки зрения использования ресурсов.

Несмотря на эти очевидные недостатки, EAV уже давно используется для решения такого рода проблем. Это были неизбежное недостатки, и лучшей альтернативы просто не было.
Но затем в PostgreSQL появилась новая “технология”…

Начиная с PostgreSQL 9.4, был добавлен тип данных JSONB для хранения двоичных данных JSON. Хотя хранение JSON в этом формате обычно занимает немного больше места и времени, чем простой текстовый JSON, выполнение операций с ним происходит намного быстрее. Также JSONB поддерживает индексирование, что делает запросы к ним еще быстрее.

Тип данных JSONB позволяет нам заменить громоздкий паттерн EAV путем добавления всего лишь одного столбца JSONB в нашу таблицу сущностей, что значительно упрощает проектирование базы данных. Но многие утверждают, что это должно сопровождаться снижением производительности… Вот по этой причине я и появилась эта статья.

Настройка тестовой базы данных


Для этого сравнения я создал базу данных на новой установке PostgreSQL 9.5 на 80-долларовой сборке DigitalOcean Ubuntu 14.04. После настройки некоторых параметров в postgresql.conf я запустил этот скрипт с помощью psql. Для представления данных в виде EAV были созданы следующие таблицы:

CREATE TABLE entity ( 
  id           SERIAL PRIMARY KEY, 
  name         TEXT, 
  description  TEXT
);
CREATE TABLE entity_attribute (
  id          SERIAL PRIMARY KEY, 
  name        TEXT
);
CREATE TABLE entity_attribute_value (
  id                  SERIAL PRIMARY KEY, 
  entity_id           INT    REFERENCES entity(id), 
  entity_attribute_id INT    REFERENCES entity_attribute(id), 
  value               TEXT
);

Ниже представлена таблица где будут хранится те же данные, но с атрибутами в столбце типа JSONB – properties.

CREATE TABLE entity_jsonb (
  id          SERIAL PRIMARY KEY, 
  name        TEXT, 
  description TEXT,
  properties  JSONB
);

Выглядит намного проще, не так ли? Затем было добавлено в таблицы сущностей (entity & entity_jsonb) 10 миллионов записей, и соответственно, было заполнено одинаковыми данными таблицы где используется EAV паттерн и подход с JSONB столбцом – entity_jsonb.properties. Таким образом, мы получили несколько разных типов данных среди всего набора свойств. Пример данных:

{
  id:          1
  name:        "Entity1"
  description: "Test entity no. 1"
  properties:  {
    color:        "red"
    lenght:       120
    width:        3.1882420
    hassomething: true
    country:      "Belgium"
  } 
}

Итак, теперь у нас есть одинаковые данные, для двух вариантов. Давайте начнем сравнивать реализации в работе!

Упрощение дизайна


Ранее уже было сказано, что дизайн БД был значительно упрощен: одна таблица, за счет использования столбца JSONB для свойств, вместо использования трех таблиц для EAV. Но как же это отражается в запросах? Обновление одного свойства сущности выглядит следующим образом:

-- EAV
UPDATE entity_attribute_value 
SET value = 'blue' 
WHERE entity_attribute_id = 1 
  AND entity_id = 120;

-- JSONB
UPDATE entity_jsonb 
SET properties = jsonb_set(properties, '{"color"}', '"blue"') 
WHERE id = 120;

Как видим, последний запрос не выглядит проще. Чтобы обновить значение свойства в объекте JSONB, мы должны использовать функцию jsonb_set(), и должны передать наше новое значение как объект JSONB. Тем не менее, нам не нужно знать какой-либо идентификатор заранее. Посмотрев на пример с EAV, нам нужно знать и entity_id, и entity_attribute_id, чтобы выполнить обновление. Если вы хотите обновить свойство в столбце JSONB на основе имени объекта, – то это все делается одной простой строкой.

Теперь давайте выберем ту сущность, которую мы только что обновили, по условию ее нового цвета:

-- EAV
SELECT e.name 
FROM entity e 
  INNER JOIN entity_attribute_value eav ON e.id = eav.entity_id
  INNER JOIN entity_attribute ea ON eav.entity_attribute_id = ea.id
WHERE ea.name = 'color' AND eav.value = 'blue';

-- JSONB
SELECT name 
FROM entity_jsonb 
WHERE properties ->> 'color' = 'blue';

Я думаю, что мы можем согласиться с тем, что второе является более коротким (без join!), и соответственно более читабельным. Здесь победа JSONB! Мы используем оператор JSON ->>, чтобы получить цвет как текстовое значение из объекта JSONB. Существует также второй способ достижения того же результата в модели JSONB с использованием оператора @>:

-- JSONB 
SELECT name 
FROM entity_jsonb 
WHERE properties @> '{"color": "blue"}';

Это немного сложнее: мы проверяем, содержит ли объект JSON в столбце свойств объект который находится справа от оператора @>. Менее читаемый, более производительный (см. далее).

Упростим использования JSONB еще сильнее, когда вам нужно выбрать несколько свойств одновременно. Вот где действительно подходит JSONB-подход: мы просто выбираем свойства в качестве дополнительных столбцов в нашем наборе результатов без необходимости объединений:

-- JSONB 
SELECT name
  , properties ->> 'color'
  , properties ->> 'country'
FROM entity_jsonb 
WHERE id = 120;

С EAV вам понадобится 2 объединения для каждого свойства, которое вы хотите запросить. На мой взгляд, приведенные выше запросы показывают большое упрощение в дизайне базы данных. Посмотреть больше примеров того, как писать запросы к JSONB, возможно также в этом посте.
Теперь пришло время поговорить о производительности.

Производительность


Чтобы сравнить производительность, я использовал EXPLAIN ANALYZE в запросах, для подсчета времени выполнения. Каждый запрос выполнялся как минимум три раза, потому что в первый раз планировщику запросов требуется больше времени. Сначала я выполнил запросы без каких-либо индексов. Очевидно, это служило преимуществом JSONB, так как join, необходимые для EAV, не могли использовать индексы (поля внешнего ключа не индексировались). После этого я создал индекс для 2-х столбцов внешних ключей таблице значений EAV, а также индекс GIN для столбца JSONB.

Обновления данных показало следующие результаты по времени (в мс). Обратите внимание, что масштаб является логарифмическим:

image

Видим что JSONB намного (> 50000-x) быстрее, чем EAV, если не использовать индексы, по причине, указанной выше. Когда мы индексируем столбцы c первичными ключами, разница почти пропадает, но JSONB все еще в 1,3 раза быстрее, чем EAV. Обратите внимание, что индекс в столбце JSONB здесь не оказывает никакого влияния, так как мы не используем столбец свойств в критериях оценки.

Для выбора данных на основе значения свойства мы получаем следующие результаты (обычный масштаб):

image

Можно заметить, что JSONB снова работает быстрее, чем EAV без индексов, но когда EAV с индексами – он все таки работает быстрее чем JSONB. Но потом я увидел, что время для JSONB-запросов было одинаковым, это подтолкнуло меня на тот факт, что GIN-индекс не срабатывают. Видимо, когда вы используете индекс GIN для столбца с заполненными свойствами, он действует только при использовании оператора включения @>. Я использовал это в новом тесте, что оказало огромное влияние на время: всего 0,153 мс! Это в 15000 раз быстрее, чем EAV, и в 25000 раз быстрее, чем оператор ->>.

Думаю, это было достаточно быстро!

Размер таблиц БД


Давайте сравним размеры таблиц при обоих подходов. В psql мы можем показать размер всех таблиц и индексов с помощью команды \dti+

image

Для подхода EAV размеры таблиц составляют около 3068 МБ, а индексы – до 3427 МБ, что в сумме дает 6,43 ГБ. При использовании подхода с JSONB используется 1817 МБ для таблицы и 318 МБ для индексов, что составляет 2,08 ГБ. Получается в 3 раза меньше! Этот факт немного удивил меня, потому что мы храним имена свойств в каждом объекте JSONB.

Но все таки цифры говорят сами за себя: в EAV мы храним 2 целочисленных внешних ключа на значение атрибута, в результате чего получаем 8 байт дополнительных данных. Кроме того, в EAV все значения свойств хранятся в виде текста, в то время как JSONB будет использовать числовые и логические значения внутри, где это возможно, в результате чего получается меньший объем.

Итоги


В целом, я думаю, что сохранение свойств сущностей в формате JSONB может значительно упростить проектирование и обслуживание вашей базы данных. Если вы выполняете много запросов, то все, что хранится в одной таблице с сущностью, действительно будет работать эффективнее. И тот факт, что это упрощает взаимодействие между данными, уже является плюсом, но и результирующая БД в 3 раза меньше по объему.

Также, по сделанным тестом, можно сделать итог, что потери производительности очень незначительные. В некоторых случаях JSONB даже работает быстрее, чем EAV, что делает его еще лучше. Однако этот эталонный тест, конечно, не охватывает все аспекты (например, сущности с очень большим количеством свойств, значительным увеличением числа свойств существующих данных,…), поэтому, если у вас есть какие-либо предложения о том, как их улучшить, пожалуйста, не стесняйтесь оставлять в комментариях!
Поделиться публикацией
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 37

    0
    explain analize наверно не лучший вариант для теста, надо проверять генегируя таблицу и делая множество разных запросов.
      0
      Как точка отсчета explain очень даже хорош. Да, можно нагрузочные придумать и посмотреть на систему в динамике, а еще никадать не 10 параметров, а 100500 с неравномерным заполнением дабы было максимально близко с реальности (интернет-магазин всего и вся например).
      Вот только есть одно НО: факт в том, что 99.9% проектов ни когда в жизни не достигнут таких объемов данных как в выборке у автора (смешные 10млн) и им куда важнее не скорость выолнения запроса, а скорость разработки этого самого проекта. И по классике жанра, все что тормозит — кладется в кэш и спят спокойно)
      +1
      Если сущность имеют 2 атрибуты, то нужно уже 4 join-на!
      Не нужно миллион джойнов, нужен один PIVOT (он в постгресе называется «crosstab» и работает вполне шустро).
      И еще...
      «join-на» — это пять! Почти как «2ва» и «3ри». Пишите хотя бы «join'а», если использовать слово «джойна» так уж не хочется.

      Кроме того, все атрибуты обычно хранятся в виде строк, что приводит к приведению типов, как для результата, так и для условия WHERE.
      Так заведите отдельные таблицы или столбцы под каждый тип.
      Если вы пишете много запросов, то это достаточно расточительно, с точки зрения использования ресурсов.
      EAV — это в принципе расточительно…
        +1
        Не нужно миллион джойнов, нужен один PIVOT

        Я всегда думал, что нужен один select, в котором в условии where будет id сущности. А джойнов надо всегда два, просто чтобы присоединить к таблице с сущностями таблицы с ключами и значениями. Хотя, честно говоря я не совсем понимаю, почему нельзя это всё сложить в одну таблицу.

        +4
        Может JSONB — это и круто, но это вообще никаким местом не полноценная замена EAV.
        EAV, в отличие от JSON, это не полный schem-less, это sheme-as-data. Там можно иметь дополнительные метаданные у полей, проводить некоторые манипуляции со структурой Entity, не перетряхивая все значения и иметь где-то фиксированную доступную для просмотра структуру записей. Еще можно делать множественные привязки, но это штука уже довольно сомнительная.
          +3
          -- JSONB
          UPDATE entity_jsonb
          SET properties = jsonb_set(properties, '{"color"}', '"blue"')
          WHERE id = 120;

          Надо иметь ввиду, что значение в колонке properties заменяется целиком. Теперь представим, что JSON-ы, которые мы храним, достаточно большие. И если типичная нагрузка — это частые обновления отдельно взятых полей JSON-а, то EAV может оказаться и на голову эффективнее.

          В общем, в статье незаслуженно обойден вопрос о производительности записи и влиянии на WAL.
            +1
            Надо иметь ввиду, что значение в колонке properties заменяется целиком. Теперь представим, что JSON-ы, которые мы храним, достаточно большие. И если типичная нагрузка — это частые обновления отдельно взятых полей JSON-а, то EAV может оказаться и на голову эффективнее.

            Если мы говорим о PostgreSQL, тип jsonb там хранится в бинарном виде, не парсится каждый раз и позволяет без проблем и быстро выбирать/заменять любое свойство внутри json( www.postgresql.org/docs/9.4/datatype-json.html ) не заменяя его полностью.
              +2
              Да, это быстро, но на физическом уровне создается новая версия строки а не перезаписывается существующая, т.е. мы получаем полную копию всего jsonb (с заменой одного поля), в то время, как в EAV — только копию строки, содержащей измененное значение. Как интенсивные обновления больших jsonb повлияют на размер WAL и TOAST-таблиц, на поведение VACUUM — вопрос, который я бы игнорировать поостерегся.

              Хотя с основным посылом я согласен — jsonb во многих случаях выглядит предпочтительнее, чем EAV. Указываю только на то, что в общем случае нагрузка на БД не сводится к одним только select-ам.
            0
            А какой именно GIN индекс строился? В этой статье рассматриваются разные варианты. Например с параметром jsonb_path_ops. Не пробовали такие варианты?
              +4
              Рассмотрим паттерн EAV (Entity-Attribute-Value), он встречается достаточно часто. Одна таблица содержит сущности (записи), другая таблица содержит имена свойств (атрибутов), а третья таблица связывает сущности с их атрибутами и содержит значение этих атрибутов для текущей сущности.

              Небольшое замечание: это не структура данных EAV, а скорее реализация связи «многие-ко-многим». Для EAV достаточно одной таблицы с тремя столбцами: собственно сущность, атрибут сущности, значение атрибута. Может быть ещё справочник атрибутов, но не обязательно.
                –3
                Не очень понятно зачем для EAV делать 2 таблицы помимо основной таблицы сущностей?

                Я работал так:
                1. таблица сущностей: entity
                2. таблица атрибутов: attributes

                у таблицы атрибутов поля:
                — id
                — entity_id
                — key
                — value

                Все. Это работает. Храним любые атрибуты и их значения.

                По любой сущности можно получить все атрибуты и значения 1 запросом с 1 join. Атрибутов моджет быть хоть 1000 штук. Доходило до 20 000 штук.

                Хранить такое в JSONB — мб плачевно.

                С другой сторону конечно же EAV это не серебрянная пуля. У нее есть как плюсы так и минусы.

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

                Есть много решений. Что то можно выдернуть в отдельные таблицы. Иногда подключается внешний индекс типа Эластика или Алголии. Например для создания поисковых индексов.

                JSONB крутая штука. Где то она будет показывать себя лучше. Но не везде )
                  +1

                  Если я не ошибаюсь, вынесения атрибутов в отдельную таблицу требует 3-я нормальная форма. И правильнее задаваться вопросом, что нам даст подобная денормализация.

                    0

                    Нет, 3НФ этого не требует. Вообще, ни одна из НФ не требует создавать отдельные суррогатные ключи для кодирования строк.

                      0
                      Нет, ну конечно, от части Вы правы. Все зависит от того, как эти атрибуты трактует бизнес логика. Если это просто строки, которые не несут особой смысловой нагрузки — тут согласен. Но если это, например, характеристики товара в магазине(как чаще всего бывает и именно этот кейс я имел в виду), по которым нужно организовывать фильтр, или если, не дай бог, от выбора характеристик зависит цена товара, то тут характеристика — это отдельное отношение и хранение ее в таком виде — очевидная денормализация.
                      Исправьте, если я неправ.
                  0
                  Проблема решена… до того момента, пока ваша таблица не содержит миллионы записей и у вас не возникнет необходимость добавить новую запись.

                  Я не понимаю, в чём проблема добавить новую запись к миллионам других. Или это опечатка, и автор имел в виду «добавить новую колонку»? Но здесь тоже нет никакой проблемы, потому что в современных движках БД строки не фиксированной длины.
                    0

                    Если записей миллионы — добавление колонки очень затратная операция в большинстве sql баз. Я бы даже скорее вынес новую колонку в отдельную таблицу 1х1 чем положил базу на пару часов добавлением новой колонки.

                      0

                      Если сделать колонку nullable, то никаких проблем не будет.

                        0

                        Спасибо, не знал этого. В Постгресе это так. Надо будет проверить как mysql будет реагировать.

                          0

                          Большой респект Постгресу. Mysql добавлял колонку как и ожидалось долго — 30с. для 1000000 строк

                      +1
                      Немного узковатое понимание jsonb. Да, он неплохо подходит для хранения атрибутов, но это не та причина, по которой его создавали — до него в постгресе с этим успешно справлялся hstore. Собственно для хранения атрибутов kv хранилища как правило хватает за глаза.
                      jsonb же выделяется тем, что быстрее json — об этом написано в статье, а также тем, что это все тот же json, в котором можно хранить не просто атрибуты, а целые структуры с вложениями, kv и списками. Быстрый доступ к таким структурам и возможность работать с такими структурами без костылей и является киллер фичей jsonb в сравнении с hstore.
                      Но это все историческая ремарка, jsonb сейчас ничуть не медленнее hstore и имеет неплохие преимущества перед ним, потому вопрос о том, что использовать в новом продукте уже и не стоит. Буду рад услышать преимущества hstore, если не прав.

                      Единственное, чего хотелось бы — типизация на уровне бд, а не на логическом уровне, но это уже капризы)
                        0

                        Я так понял, что hstore — это чисто PostgreSQL изобретение. А jsonb — стандарт. Hstore появился до JSON или до популярности JSON, видимо, jsonb призван со временем его заменить.

                        0

                        А если свойство может иметь несколько вариантов? {"Ram":[{"ddr3","sdram"}]}. Как проапдейтить или удалить определённое? Если на сотнях, тысячах записей?

                          0

                          В моём пет-проекте используется EAV. Наелся этого по самое нихочу.
                          Автор ничтоже сумняше не раскрыл один момент. Трёхтабличный EAV это не более чем пример практики, в реальности что-то адекватное можно построить не менее чем на 7. В моём проекте эта схема реализована на 9 и планирую расширить до 12 в ближайшей перспективе.
                          Благодаря этому я сохранил преимущества EAV плюс добился того что атрибуты хранятся в БД в своём типе, а не в строке. Недостатки остались конечно.
                          Вопрос производительности остаётся открытым и стоит остро. Метрики этого пока не собираю.

                            0

                            Статья от января 2016 года… У нас в проектах, тянущихся с тех времен, похожие решения используются. Но все-таки уже почти три года прошло с тех пор.


                            Заголовок спойлера

                            Хочется EAV — попробуй RDF-хранилище.
                            Тормозят JOIN'ы — используй графовую СУБД.
                            Любишь JSON — есть документные СУБД.

                              +2
                              Не, ну… Я конечно за то чтобы подбирать инструменты под задачу, но в данном случае это зоопарк технологий непонятно для чего.

                              Хочется EAV — попробуй RDF-хранилище.

                              Зачем? Ну если только в пет-проекте попробовать…

                              Тормозят JOIN'ы — используй графовую СУБД.

                              Может лучше разобраться чего они тормозят?

                              Любишь JSON — есть документные СУБД.

                              Ну пусть дальше будут. Если основная СУБД у меня PostgreSQL я знаю что он вполне себе уже лет 10 как «Not Only SQL», и в текущем состоянии вряд-ли чем-то уступает какой-нибудь Монге( www.youtube.com/watch?v=SNzOZKvFZ68 )

                              Ну и да — Документо-ориентированные СУБД подразумевают немного другие подходы к декомпозиции в принципе, потому для стандартной модели с реляциями не подходят.
                                0
                                Не, ну… Я конечно за то чтобы подбирать инструменты под задачу, но в данном случае это зоопарк технологий непонятно для чего.

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


                                Что до зоопарка самого по себе…

                                «NoSQL Distilled» Фаулера и Садаладжа в оригинале имеет вовсе не такой заголовок, как в переводе. Зоопарк (polyglot persistence), видимо, неизбежное следствие NoSQL, о чем читатели оригинала были честно предупреждены. Возникающие проблемы авторы предвидели, но недооценили. В связи с чем придумывают мультимодельные СУБД (немного писал о них здесь). PostgreSQL в качестве мультимодельной СУБД скорее не рассматривают, чем рассматривают.


                                Зачем? Ну если только в пет-проекте попробовать…

                                Какой был самый большой бюджет у проекта, в котором вам доводилось участвовать? Я наверняка смогу указать «пет-проект» с большим бюджетом.


                                Может лучше разобраться чего они тормозят?

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




                                apapacy, a Couchbase не пробовали?

                                +1

                                По документо-ориентированным DB — много вопросов возникает сейчас. Когда-то на волне хайпа я юзал монгу с nodejs. На тот момент сравнение производительности с теми же postgres+nodejs и mysql+nodejs выглядело сильно в пользу mongo+nodejs. Сейчас выигрыш по insert уже не наблюдается. (Причина неясна, скорее всего драйверы для nodejs были не очень производительные). Плюс у postgresql появился bson. Что имеем в итоге. Постгрес с bson перегрывает весь функционал mongodb и не уступает в производительности. Плюс дает возможность без проблем делать выборки с join, sum, like — чего не очень удобно делать в mongodb

                                +2
                                Если взять интернет-магазин, то таблицу entity_attribute при использовании jsonb все таки заводить придется, т.к. нужно будет учесть, что значения в entity_attribute:
                                — могут выбираться из списка (цвет товара, класс пожарной опасности).
                                — могут быть произвольным текстовым полем (название материала подошвы кроссовок)
                                — могут быть числом с заранее заданным диапазоном (размер шкафа, положительное целое число со значениями от и до)
                                — хранимое значение и вывод этого значения могут отличаться (водостойкость/морозостойкость в БД хранится, как true/false, а на выходе должно быть отсутствует/присутствует или да/нет или 0/1 или еще как-нибудь)
                                — может быть обязательным к заполнению или нет
                                — возможно значение по умолчанию
                                — единица измерения значения (ширира обоев в см, длина обоев в метрах)

                                Подскажите, а есть ли какие-нибудь цифры по построению фасетных фильтров при использовании EAV и JSONB?
                                  0

                                  Это всё конечно хорошо, но одним sql сыт не будешь, а orm поддерживают jsonb плохо. Пытался мигрировать с eav на jsonb, но бросил т. к. каждый раз извлекаешь json целиком и парсишь его, чтобы извлечь/изменить нужный атрибут.
                                  Хотя по месту выигрыш был сладкий — 10+ 2Gb индексов превратились в 2.5 +0.6 Gb.

                                    0
                                    Так есть же операторы позволяющие извлекать конкретные значения из JSON документа, и менять. А с 12 версии в Постгре вообще полноценная поддержка JSONPath.
                                      0
                                      Это все прекрасно и этим удобно пользоваться в рамках raw sql. Но если вы посмотрите на реализации поддержки JSONB в, например, Hibernate вы увидите использование jackson, а не ->, ->>, <@ и.т.д.
                                    –1
                                    ЯННП, зачем вспоминать EAV, когда давно изобрели монгу?
                                      0

                                      В принципе статья хорошая в плане направления исследования. Я сам был уверен что индекс по bson работает дольше чем обычный.


                                      Но.


                                      Автор забыл определить индекс для поля value, чем сделал результаты просто неверными.


                                      Я решил перепроверить — уж очень большая была разница и добавил индекс на поле value


                                      Разница была и не очень существенная. Первый запрос по GIN было более продолжительое планирование. При повторных запросах планирование существенно (в 100 раз) сократилось и запрос по GIN был быстрее ( 1,2 мс против 1,3 мс). Но все же это не так у автора 1000-х разница

                                        0
                                        Автор забыл определить индекс для поля value, чем сделал результаты просто неверными.

                                        Ха, я и смотрю, какие-то фантастические результаты у автора получились.
                                        0
                                        Ведь стоило добавить к таблице entity_attribute_value многоколоночный btree-индекс (value, entity_attribute_id, entity_id),
                                        как снова производительность возрастает в несколько раз, но теперь уже не в пользу jsonb и gin-индекса.
                                          0

                                          Я не добавлял многоколоночный (добавил одноколоночный), скорость практически одинаковая. Но все же немного ниже на 0,1 мс. Возможно на моем конкретном комьютере и с моими конкретными данными.


                                          Скорее всего скорость может немного просесть если будет большой json объект с большим количеством свойств.


                                          Впрочем это (то есть равноценность) вполне ожидаема, т.к. для чего иначе это было разрабатывать.

                                            0
                                            На счёт равноценности Вы в целом правы, но после многих update производительность выборки из gin либо деградирует (при включенном fastupdate), либо сами update сильно замедляются (при выключенном fastupdate). Этого недостатка нет у btree.

                                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                        Самое читаемое