Elasticsearch — это распределенная поисковая и аналитическая система на основе с открытым исходным кодом, созданная с использованием Apache Lucene для обеспечения быстрого поиска в реальном времени. Это хранилище данных NoSQL, которое по умолчанию ориентировано на документы, масштабируется и не имеет схемы. Elasticsearch предназначен для масштабной работы с большими наборами данных. Как поисковая система, она обеспечивает быструю индексацию и возможности поиска, которые можно горизонтально масштабировать по нескольким узлам. JSON Бесстыдная пробка: — это база данных индексации в реальном времени в облаке. Он автоматически создает индексы, оптимизированные не только для поиска, но также для агрегирования и объединения, что позволяет вашим приложениям быстро и легко запрашивать данные, независимо от того, откуда они получены и в каком формате. Но в этой статье освещаются некоторые обходные пути. , если вы действительно хотите выполнять соединения в стиле SQL в Elasticsearch. Rockset Почему отношения между данными имеют значение? Мы живем в тесно связанном мире, где обработка взаимосвязей данных имеет важное значение. Реляционные базы данных хорошо справляются с отношениями, но из-за постоянно меняющихся бизнес-требований фиксированная схема этих баз данных приводит к проблемам с масштабируемостью и производительностью. Использование хранилищ данных NoSQL становится все более популярным благодаря их способности решать ряд проблем, связанных с традиционными подходами к обработке данных. Предприятия постоянно имеют дело со сложными структурами данных, где для анализа данных требуются возможности агрегирования, объединения и фильтрации. С ростом неструктурированных данных растет число случаев использования, требующих объединения данных из разных источников для целей анализа данных. Хотя соединения в первую очередь относятся к концепции SQL, они не менее важны и в мире NoSQL. Объединения в стиле SQL не поддерживаются в Elasticsearch как первоклассные граждане. В этой статье будет обсуждаться, как определять отношения в Elasticsearch с использованием различных методов, таких как денормализация, соединения на стороне приложения, вложенные документы и отношения «родитель-потомок». Также будут изучены варианты использования и проблемы, связанные с каждым подходом. Как работать с отношениями в Elasticsearch Поскольку Elasticsearch не является реляционной базой данных, соединения не существуют в качестве встроенной функции, как в базе данных SQL. Он больше фокусируется на эффективности поиска, а не на эффективности хранения. Сохраненные данные практически выравниваются или денормализуются для обеспечения быстрого поиска. Существует несколько способов определения отношений в Elasticsearch. В зависимости от вашего варианта использования вы можете выбрать в Elasticsearch один из следующих методов для моделирования ваших данных: Отношения «один к одному»: сопоставление объектов Отношения «один ко многим»: вложенные документы и модель «родитель-потомок». Отношения «многие ко многим»: денормализация и соединения на стороне приложения Сопоставления объектов «один к одному» просты и не будут здесь подробно обсуждаться. В оставшейся части этого блога два других сценария будут рассмотрены более подробно. Управление вашей моделью данных в Elasticsearch Существует четыре распространенных подхода к управлению данными в Elasticsearch: Денормализация Объединения на стороне приложения Вложенные объекты Отношения между родителями и детьми Денормализация Денормализация обеспечивает наилучшую производительность поиска по запросам в Elasticsearch, поскольку объединение наборов данных во время запроса не требуется. Каждый документ независим и содержит все необходимые данные, что устраняет необходимость в дорогостоящих операциях соединения. При денормализации данные сохраняются в плоской структуре во время индексации. Однако это увеличивает размер документа и приводит к хранению дублирующихся данных в каждом документе. Дисковое пространство не является дорогим товаром и поэтому не вызывает особого беспокойства. Варианты использования денормализации При работе с распределенными системами необходимость объединения наборов данных по сети может привести к значительным задержкам. Вы можете избежать этих дорогостоящих операций соединения, денормализуя данные. Отношения «многие ко многим» можно обрабатывать путем выравнивания данных. Проблемы с денормализацией данных Дублирование данных в плоские документы требует дополнительного места для хранения. Управление данными в плоской структуре влечет за собой дополнительные накладные расходы для наборов данных, которые являются реляционными по своей природе. С точки зрения программирования денормализация требует дополнительных инженерных затрат. Вам потребуется написать дополнительный код, чтобы свести данные, хранящиеся в нескольких реляционных таблицах, и сопоставить их с одним объектом в Elasticsearch. Денормализация данных не является хорошей идеей, если ваши данные часто меняются. В таких случаях денормализация потребует обновления всех документов, когда изменится какое-либо подмножество данных, и поэтому ее следует избегать. Операция индексирования со сглаженными наборами данных занимает больше времени, поскольку индексируется больше данных. Если ваши данные часто меняются, это будет означать, что ваша скорость индексации выше, что может вызвать проблемы с производительностью кластера. Объединения на стороне приложения Объединения на стороне приложения можно использовать, когда необходимо поддерживать связь между документами. Данные хранятся в отдельных индексах, а операции соединения могут выполняться со стороны приложения во время запроса. Однако это влечет за собой выполнение дополнительных запросов во время поиска из вашего приложения для объединения документов. Варианты использования соединений на стороне приложения Объединения на стороне приложения гарантируют, что данные остаются нормализованными. Изменения производятся в одном месте, и нет необходимости постоянно обновлять документы. При таком подходе избыточность данных сводится к минимуму. Этот метод хорошо работает, когда документов меньше и данные изменяются реже. Проблемы с соединениями на стороне приложения Приложению необходимо выполнить несколько запросов для объединения документов во время поиска. Если набор данных имеет много потребителей, вам придется выполнять один и тот же набор запросов несколько раз, что может привести к проблемам с производительностью. Таким образом, этот подход не использует реальную мощь Elasticsearch. Такой подход приводит к сложности на уровне реализации. Требуется написание дополнительного кода на уровне приложения для реализации операций соединения и установления связи между документами. Вложенные объекты Вложенный подход можно использовать, если вам необходимо поддерживать взаимосвязь каждого объекта в массиве. Вложенные документы хранятся внутри как отдельные документы Lucene и могут быть объединены во время запроса. Это соединения во время индексирования, при которых несколько документов Lucene хранятся в одном блоке. С точки зрения приложения блок выглядит как один документ Elasticsearch. Таким образом, запросы выполняются относительно быстрее, поскольку все данные находятся в одном и том же объекте. Вложенные документы имеют дело с отношениями «один ко многим». Варианты использования вложенных документов Создание вложенных документов предпочтительнее, если ваши документы содержат массивы объектов. На рисунке 1 ниже показано, как вложенный тип в Elasticsearch позволяет внутренне индексировать массивы объектов как отдельные документы Lucene. В Lucene нет понятия внутренних объектов, поэтому интересно посмотреть, как Elasticsearch внутренне преобразует исходный документ в сглаженные многозначные поля. Одним из преимуществ использования вложенных запросов является то, что они не будут выполнять сопоставления между объектами, что позволяет избежать неожиданных результатов сопоставления. Он учитывает границы объектов, что делает поиск более точным. Рис. 1. Массивы объектов, индексированных внутри как отдельные документы Lucene в Elasticsearch с использованием вложенного подхода. Проблемы с вложенными объектами Корневой объект и его вложенные объекты должны быть полностью переиндексированы, чтобы добавить/обновить/удалить вложенный объект. Другими словами, обновление дочерней записи приведет к переиндексации всего документа. Вложенные документы не могут быть доступны напрямую. Доступ к ним возможен только через соответствующий корневой документ. Поисковые запросы возвращают весь документ, а не только вложенные документы, соответствующие поисковому запросу. Если ваш набор данных часто меняется, использование вложенных документов приведет к большому количеству обновлений. Отношения между родителями и детьми Отношения «родитель-потомок» используют , чтобы полностью разделить объекты со связями на отдельные документы — родительский и дочерний. Это позволяет хранить документы в реляционной структуре в отдельных документах Elasticsearch, которые можно обновлять отдельно. тип данных соединения Отношения между родителями и детьми полезны, когда документы необходимо часто обновлять. Поэтому этот подход идеально подходит для сценариев, когда данные часто меняются. По сути, вы разделяете базовый документ на несколько документов, содержащих родительский и дочерний элементы. Это позволяет индексировать/обновлять/удалять как родительские, так и дочерние документы независимо друг от друга. Поиск в родительских и дочерних документах Чтобы оптимизировать производительность Elasticsearch во время индексации и поиска, общая рекомендация — следить за тем, чтобы размер документа был небольшим. Вы можете использовать модель «родитель-потомок», чтобы разбить документ на отдельные документы. Однако существуют некоторые проблемы с реализацией этого. Родительские и дочерние документы должны быть перенаправлены в один и тот же сегмент, чтобы их объединение во время запроса происходило в памяти и было эффективным. Родительский идентификатор необходимо использовать в качестве значения маршрутизации для дочернего документа. Поле предоставляет Elasticsearch идентификатор и тип родительского документа, что позволяет ему направлять дочерние документы в тот же сегмент, что и родительский документ. _parent Elasticsearch позволяет выполнять поиск по сложным объектам JSON. Однако для эффективного выполнения запросов требуется глубокое понимание структуры данных. Модель «родитель-потомок» использует несколько фильтров для упрощения функции поиска: запрос has_child Возвращает родительские документы, у которых есть дочерние документы, соответствующие запросу. запрос has_parent Принимает родительский элемент и возвращает дочерние документы, которым сопоставлены связанные родительские элементы. запрос inner_hits Извлекает соответствующую информацию о дочерних элементах из запроса . has_child На рис. 2 показано, как можно использовать модель «родитель-потомок» для демонстрации отношений «один ко многим». Дочерние документы можно добавлять/удалять/обновлять, не затрагивая родительский. То же самое справедливо и для родительского документа, который можно обновлять без переиндексации дочерних документов. Рисунок 2. Модель «родитель-потомок» для отношений «один ко многим». Проблемы в отношениях между родителями и детьми Запросы более дороги и требуют больше памяти из-за операции соединения. Конструкции «родитель-потомок» требуют дополнительных затрат, поскольку они представляют собой отдельные документы, которые необходимо объединить во время запроса. Необходимо убедиться, что родительский элемент и все его дочерние элементы существуют на одном шарде. Хранение документов с отношениями родитель-потомок связано со сложностью реализации. Заключение Выбор правильной схемы Elasticsearch имеет решающее значение для производительности и удобства обслуживания приложения. При разработке модели данных в Elasticsearch важно учитывать различные плюсы и минусы каждого из четырех методов моделирования, обсуждаемых здесь. моделирования данных В этой статье мы рассмотрели, как вложенные объекты и отношения «родитель-потомок» позволяют выполнять SQL-подобные операции соединения в Elasticsearch. Вы также можете реализовать в своем приложении собственную логику для обработки отношений с соединениями на стороне приложения. В случаях использования, когда вам необходимо объединить несколько наборов данных в Elasticsearch, вы можете принять и загрузить оба этих набора данных в индекс Elasticsearch, чтобы обеспечить производительность запросов. По умолчанию Elasticsearch не имеет объединений, как в базе данных SQL. Несмотря на то, что существуют потенциальные обходные пути для установления взаимосвязей в ваших документах, важно осознавать проблемы, которые представляет каждый из этих подходов. Использование собственных SQL-соединений с Rockset Когда возникает необходимость объединить несколько наборов данных для анализа в реальном времени, база данных, которая обеспечивает собственные соединения SQL, может лучше справиться с этим вариантом использования. Как и Elasticsearch, Rockset используется в качестве слоя индексации данных из баз данных, потоков событий и озер данных, что позволяет осуществлять бессхемный прием данных из этих источников. В отличие от Elasticsearch, Rockset предоставляет возможность , включая соединения, что дает вам большую гибкость в использовании ваших данных. выполнять запросы с помощью полнофункционального SQL Также опубликовано . здесь