Альтернатива EAV для динамических полей в хранилище данных схемы типа звезда

13

Мне нужно поддерживать динамические поля и значения в большом хранилище данных для хранения журнала запросов API, в моем случае пользователь должен хранить строку запроса всех запросов API и иметь возможность выполнять запрос к ним в будущем (так что это не просто хранилище, поэтому я не могу использовать BLOB для них)

например http://example.com/?action=test&foo=abc&bar=def...

Мне нужно хранить все field => valueсопоставления, т. Е. (action => test), (foo => abc), (bar => def)Поскольку поле является таким динамическим, единственное решение, которое я нашел, - это использовать Entity-Attribute-Value, однако люди продолжают говорить, что это очень плохой дизайн.

Итак, рассмотрим мой вариант использования выше, что будет подходящей альтернативой EAV?

Моя текущая схема с использованием KAV

  1. Таблица, requests
    (id, timestamp, uri)
    например(1, 149382220, '/')

  2. Таблица, params
    (request_id, key, value)
    например(1, 'action', 'test'), (1, 'foo', 'abc'), (1, 'bar', 'def')

Какие-либо предложения?

Обновление: запускаем склад на AWS RedShift

Говард
источник
2
Что плохого в том, чтобы попробовать то, что вы предлагаете в базе данных разработчиков? Кроме того, вы говорите о SQL Server? SQL тег довольно широк.
Макс Вернон
Обновил мой вопрос
Говард
1
Какую СУБД вы используете? Некоторые из них имеют довольно хорошие возможности индексирования текста, поэтому я не исключаю использование поля «длинный текст» для хранения запросов. Сказав это, у меня не будет проблем с использованием модели, которую вы предлагаете. Хотя EAV в строгом смысле этого слова, он используется только для этой цели. Опять же, сказав это, какие запросы нужно выполнить? Попробуйте написать эти запросы к этой модели, чтобы увидеть, работает ли она для вас.
Colin 't Hart
1
Какие СУБД вы используете? SQLне достаточно конкретен. Вас спросили дважды. Я третий.
Эрвин Брандштеттер,
2
Поскольку RedShift базируется на PostgreSQL, я хотел бы попробовать использовать hstoreили jsonтип данных (или , jsonbесли / когда они «обновить» до 9.4).
Colin 't Hart

Ответы:

11

Я могу придумать три решения - EAV, XML и Sparse Columns. Последнее зависит от поставщика и может оказаться бесполезным для вас.

Какой бы метод вы ни выбрали, вы можете рассмотреть возможность сохранения исходных данных запроса в необработанном формате, в виде таблицы или плоского файла. Это позволит легко опробовать новые способы хранения данных, позволит перезагрузить данные, если вы обнаружите ошибку при анализе ваших запросов, и предложит возможности для анализа запросов API с помощью пакетной обработки или «больших данных». инструменты, если вы обнаружите, что ваше хранилище данных не в состоянии эффективно обрабатывать данные.

EAV соображения

EAV / KVS, как вы описали выше, вероятно, будет самой простой реализацией.

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

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

XML

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

Загрузка запроса API в базу данных в виде XML обеспечит один кортеж на запрос, что логически может быть более приемлемым для вас, чем наличие неизвестного количества строк в таблице EAV.

Эффективность этого будет во многом зависеть от вашего поставщика RDBMS и вашей реализации.

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

Разреженные столбцы / традиционные таблицы

Возможно, вы могли бы загрузить свои данные в традиционную структуру таблицы, с одним столбцом на ключ.

Функция Sparse Columns в SQL Server - отличная альтернатива хранилищу EAV. Таблица с разреженными столбцами ведет себя так же, как обычная таблица, за исключением того, что она может содержать до 30 000 столбцов, а значения NULL в разреженных столбцах не занимают места в таблице.

Объединение их с отфильтрованными индексами (еще одна особенность SQL Server) может обеспечить чрезвычайно эффективную альтернативу хранилищу EAV, если вы часто запрашиваете пару конкретных столбцов и / или значений.

Использование традиционной таблицы с другими поставщиками может быть целесообразным - IBM поддерживает более 700 столбцов на таблицу, а Oracle - около 1000, а такие функции, как сжатие или обработка завершающих нулей Oracle, могут означать, что вы можете хранить свои данные API довольно эффективно.

Очевидный недостаток этого подхода заключается в том, что по мере добавления новых ключей в API вам необходимо соответствующим образом изменить свою схему.

Натан Джолли
источник
2
В PostgreSQL я бы не рекомендовал XML, но либо, hstoreлибо json. В ближайшие 9.4 jsonbбудет моя рекомендация.
Colin 't Hart
Мне очень нравится этот ответ с плюсами и минусами объяснения каждого. Очень информативно - я определенно ценю информацию о разреженных столбцах. Я хотел бы привести пример EAV с использованием метода разреженных столбцов.
StixO
9

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

Когда я разработал систему для хранения строк запроса, я понятия не имел , заранее , какие поля мне было бы интересно. Я создал таблицу для хранения строки запроса в сериализации двоичного формата, и построил систему , которая позволила мне раскололось запрос разбить его на части, как только я узнаю, какие части меня интересуют. Оттуда я создал набор таблиц; по одному для наборов данных, обычно содержащихся в строке запроса.

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

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

Макс Вернон
источник
1
В вопросе и ответе используется термин, BLOBкоторый означает двоичный длинный объект. Я бы предпочел использовать CLOB(Character Long OBject) или что-то вроде textPostgreSQL, так как мы говорим о символах, а не двоичных данных.
Colin 't Hart
2
Я использовал двоичное поле, так как фактически сериализовал весь объект сеанса и сохранил все это в базе данных.
Макс Вернон