Ожидания клиентов и соответствующие требования к приложениям никогда не были выше. Пользователи ожидают, что приложения будут быстрыми, надежными и доступными. Кроме того, данные имеют решающее значение, и пользователи хотят иметь возможность анализировать агрегированные данные по мере необходимости, чтобы получить ценную информацию. Пользователи не хотят ждать, пока инженеры по обработке данных предоставят новые индексы или создадут новые цепочки ETL. Им нужен беспрепятственный доступ к самым свежим данным. Но удовлетворение всех потребностей вашего приложения — непростая задача для любой отдельной базы данных. Для базы данных оптимизация для частых операций с малой задержкой над отдельными записями отличается от оптимизации для менее частых агрегаций или жесткой фильтрации по множеству записей. Часто мы пытаемся обработать оба шаблона с помощью одной и той же базы данных и сталкиваемся с нестабильной производительностью по мере масштабирования нашего приложения. Мы думаем, что оптимизируем с минимальными усилиями и затратами, хотя на самом деле мы делаем наоборот. Запуск аналитики в базе данных OLTP обычно требует избыточного выделения базы данных для учета пиков трафика. В конечном итоге это стоит больших денег и обычно не обеспечивает приятного взаимодействия с конечным пользователем. В этом пошаговом руководстве мы увидим, как удовлетворить высокие требования пользователей с обоими этими шаблонами доступа. Мы будем создавать финансовое приложение, в котором пользователи будут записывать транзакции и просматривать последние транзакции, а также будут нуждаться в сложной фильтрации или агрегировании своих прошлых транзакций. Гибридный подход Для удовлетворения потребностей наших приложений мы будем использовать с . DynamoDB будет обрабатывать наши основные шаблоны доступа к транзакциям — записывать транзакции и предоставлять пользователям информацию о последних транзакциях. Rockset дополнит DynamoDB для обработки наших «восхитительных» шаблонов доступа к большим объемам данных. Мы позволим нашим пользователям фильтровать по времени, продавцу, категории или другим полям, чтобы найти соответствующие транзакции, или выполнять мощные статистические вычисления для просмотра тенденций расходов с течением времени. Amazon DynamoDB Rockset Работая над этими шаблонами, мы увидим, насколько каждая из этих систем подходит для поставленной задачи. DynamoDB превосходно справляется с основными операциями OLTP — чтением или записью отдельного элемента или получением диапазона последовательных элементов на основе известных фильтров. Благодаря способу разделения данных на основе первичного ключа DynamoDB может обеспечить стабильную производительность для этих типов запросов в любом масштабе. И наоборот, Rockset превосходно справляется с непрерывным приемом больших объемов данных и применением нескольких стратегий индексации этих данных для обеспечения высокоселективной фильтрации, агрегирования в реальном времени или во время запроса, а также других шаблонов, с которыми DynamoDB не может легко справиться. Работая над этим примером, мы изучим как фундаментальные концепции, лежащие в основе двух систем, так и практические шаги для достижения наших целей. Вы можете следить за приложением, используя . репозиторий GitHub Реализация основных функций с помощью DynamoDB Мы начнем это пошаговое руководство с реализации основных функций нашего приложения. Это обычная отправная точка для любого приложения, поскольку вы создаете стандартные операции «CRUDL», обеспечивающие возможность манипулировать отдельными записями и составлять список набора связанных записей. Для приложения электронной коммерции это будет функция размещения заказа и просмотра предыдущих заказов. Для приложения для социальных сетей это будет создание публикаций, добавление друзей или просмотр людей, на которых вы подписаны. Эта функциональность обычно реализуется базами данных, которые специализируются на рабочих процессах , в которых особое внимание уделяется множеству одновременных операций с небольшим количеством строк. оперативной обработки транзакций (OLTP) В этом примере мы создаем приложение для финансирования бизнеса, где пользователь может совершать и получать платежи, а также просматривать историю своих транзакций. В этом пошаговом руководстве пример намеренно упрощен, но вы можете придумать три основных шаблона доступа для нашего приложения: , в которой будет храниться запись о платеже, сделанном или полученном предприятием; Запись транзакции , что позволит пользователям видеть самые последние платежи, сделанные и полученные компанией; и Просмотр транзакций по диапазону дат , который позволит пользователю детализировать особенности отдельной транзакции. Просмотр отдельной транзакции Каждый из этих шаблонов доступа представляет собой критический шаблон доступа большого объема. Мы будем постоянно записывать транзакции для пользователей, и лента транзакций будет первой, когда они откроют приложение. Кроме того, каждый из этих шаблонов доступа будет использовать известные согласованные параметры для извлечения соответствующих записей. Мы будем использовать DynamoDB для обработки этих шаблонов доступа. DynamoDB — это база данных NoSQL, предоставляемая AWS. Это полностью управляемая база данных, и ее популярность растет как в крупномасштабных, так и в бессерверных приложениях. Одна из самых уникальных особенностей DynamoDB заключается в том, что она обеспечивает стабильную производительность в любом масштабе. Независимо от того, составляет ли ваша таблица 1 мегабайт или 1 петабайт, вы должны видеть одинаковое время отклика для своих операций. Это желательное качество для основных сценариев использования OLTP, подобных тем, которые мы реализуем здесь. Это великое и ценное инженерное достижение, но важно понимать, что оно было достигнуто за счет избирательного подхода к типам запросов, которые будут выполняться хорошо. DynamoDB может обеспечить такую стабильную производительность благодаря двум основным конструктивным решениям. Во-первых, каждая запись в вашей таблице DynamoDB должна содержать первичный ключ. Этот первичный ключ состоит из ключа раздела, а также необязательного ключа сортировки. Второе ключевое решение DynamoDB заключается в том, что API жестко требует использования первичного ключа — подробнее об этом позже. На изображении ниже показаны примеры данных транзакций в нашем приложении FinTech. В нашей таблице используется ключ раздела названия организации в нашем приложении, а также ключ сортировки на основе , который обеспечивает характеристики уникальности UUID, а также возможность сортировки по времени создания, что позволяет нам выполнять запросы на основе времени. ULID Записи в нашей таблице включают в себя другие атрибуты, такие как название продавца, категорию и сумму, которые полезны в нашем приложении, но не так важны для базовой архитектуры DynamoDB. Важная часть находится в первичном ключе и, в частности, в ключе раздела. DynamoDB разделит ваши данные на несколько разделов хранилища, каждый из которых будет содержать подмножество данных вашей таблицы. DynamoDB использует элемент ключа раздела первичного ключа для назначения данной записи определенному разделу хранилища. По мере увеличения объема данных в вашей таблице или трафика к вашей таблице DynamoDB будет добавлять разделы для горизонтального масштабирования вашей базы данных. Как упоминалось выше, второе ключевое решение DynamoDB заключается в том, что API строго требует использования первичного ключа. Почти для всех действий API в DynamoDB требуется как минимум ключ раздела вашего первичного ключа. Благодаря этому DynamoDB может быстро направить любой запрос к нужному разделу хранилища, независимо от количества разделов и общего размера таблицы. Эти два компромисса неизбежно приводят к ограничениям в использовании DynamoDB. Вы должны заранее тщательно спланировать и разработать свои шаблоны доступа, поскольку ваш первичный ключ должен участвовать в ваших шаблонах доступа. Изменение шаблонов доступа позднее может оказаться затруднительным и может потребовать некоторых действий по переносу вручную. Если ваши варианты использования соответствуют основным компетенциям DynamoDB, вы пожнете плоды. Вы получите стабильную, предсказуемую производительность независимо от масштаба и не увидите долгосрочного ухудшения качества вашего приложения с течением времени. Кроме того, вы получите полностью управляемый опыт с низкой операционной нагрузкой, что позволит вам сосредоточиться на том, что важно для бизнеса. Основные операции в нашем примере идеально подходят для этой модели. При получении потока транзакций для организации в нашем приложении будет доступен идентификатор организации, который позволит нам использовать операцию DynamoDB для получения непрерывного набора записей с одним и тем же ключом раздела. Чтобы получить дополнительные сведения о конкретной транзакции, нам понадобится как идентификатор организации, так и идентификатор транзакции, чтобы сделать запрос DynamoDB для получения желаемого элемента. запроса GetItem Вы можете увидеть эти операции в действии на . Следуйте инструкциям, чтобы развернуть приложение и заполнить его образцами данных. Затем выполните HTTP-запросы к развернутой службе, чтобы получить канал транзакций для отдельных пользователей. Эти операции будут быстрыми и эффективными независимо от количества одновременных запросов или размера вашей таблицы DynamoDB. примере приложения Дополнение DynamoDB с помощью Rockset До сих пор мы использовали DynamoDB для обработки наших основных шаблонов доступа. DynamoDB отлично подходит для этих шаблонов, поскольку ее секционирование на основе ключей обеспечивает стабильную производительность в любом масштабе. Однако DynamoDB не очень хорошо справляется с другими шаблонами доступа. DynamoDB не позволяет эффективно выполнять запросы по атрибутам, отличным от первичного ключа. Вы можете использовать для переиндексации ваших данных по дополнительным атрибутам, но это все равно может быть проблематичным, если у вас много разных атрибутов, которые могут использоваться для индексации ваших данных. вторичные индексы DynamoDB Кроме того, DynamoDB не предоставляет никаких функций агрегирования «из коробки». Вы можете рассчитывать свои собственные агрегаты с помощью DynamoDB, но это может быть с меньшей гибкостью или с неоптимизированным потреблением операций чтения по сравнению с решением, которое заранее предназначено для агрегирования. Для обработки этих шаблонов мы . дополним DynamoDB Rockset Rockset лучше всего рассматривать как вторичный набор индексов ваших данных. Rockset использует только эти индексы во время запроса и не проецирует никакой нагрузки обратно на DynamoDB во время чтения. Вместо отдельных транзакционных обновлений от клиентов вашего приложения Rockset предназначен для непрерывного потокового приема из вашего основного хранилища данных. Он имеет прямые соединители для ряда основных хранилищ данных, включая DynamoDB, MongoDB, Kafka и многие реляционные базы данных. Когда Rockset получает данные из вашей основной базы данных, он затем индексирует ваши данные в , который заимствует концепции: индекса строки, инвертированного индекса и столбцового индекса. Дополнительные индексы, такие как диапазон, тип и геопространственные данные, автоматически создаются на основе принятых типов данных. Ниже мы обсудим особенности этих индексов, но этот конвергентный индекс обеспечивает более гибкие шаблоны доступа к вашим данным. конвергентном индексе Это основная концепция Rockset — это вторичный индекс ваших данных, использующий полностью управляемый конвейер приема данных практически в реальном времени из вашего основного хранилища данных. Команды уже давно извлекают данные из DynamoDB для вставки в другую систему для обработки дополнительных вариантов использования. Прежде чем мы перейдем к особенностям того, как Rockset получает данные из вашей таблицы, давайте кратко обсудим, чем Rockset отличается от других вариантов в этой области. Есть несколько основных отличий между Rockset и другими подходами. Во-первых, Rockset полностью управляем. Вам не только не требуется управлять инфраструктурой базы данных, но вам также не нужно поддерживать конвейер для извлечения, преобразования и загрузки данных в Rockset. Во многих других решениях вы отвечаете за «связывающий» код между вашими системами. Эти системы критически важны, но подвержены сбоям, поскольку вы должны защищаться от любых изменений в структуре данных. Изменения в восходящем направлении могут привести к неприятностям для тех, кто поддерживает эти системы. Во-вторых, Rockset может обрабатывать данные в реальном времени изменяемым образом. Со многими другими системами вы получаете то или другое. Вы можете выбрать периодический экспорт и массовую загрузку данных, но это приводит к тому, что данные между загрузками устаревают. В качестве альтернативы вы можете передавать данные в хранилище данных в потоковом режиме только для добавления, но вы не можете выполнять обновления на месте при изменении данных. Rockset может обрабатывать обновления существующих элементов так же быстро и эффективно, как и вставлять новые данные, и, таким образом, может дать вам возможность просматривать изменяющиеся данные в режиме реального времени. В-третьих, Rockset автоматически генерирует свои индексы. Другие «полностью управляемые» решения по-прежнему требуют настройки индексов, поскольку они необходимы для поддержки новых запросов. Механизм запросов Rockset предназначен для использования одного набора индексов для поддержки любых запросов. По мере того, как вы добавляете в свою систему все больше и больше запросов, вам не нужно добавлять дополнительные индексы, занимающие все больше места и вычислительных ресурсов. Это также означает, что специальные запросы также могут полностью использовать индексы, делая их быстрыми, не дожидаясь, пока администратор добавит специальный индекс для их поддержки. Как Rockset получает данные из DynamoDB Теперь, когда мы знаем основы того, что такое Rockset и как он нам помогает, давайте подключим нашу таблицу DynamoDB к Rockset. При этом мы узнаем, как работает процесс приема Rockset и чем он отличается от других вариантов. Rockset имеет специальные соединители для ряда источников данных, и конкретная реализация соединителя зависит от особенностей исходного источника данных. Для подключения к DynamoDB Rockset использует . DynamoDB Streams — это функция отслеживания измененных данных DynamoDB, при которой в поток записываются подробности каждой операции записи в таблицу DynamoDB. Потребители потока могут обрабатывать эти изменения в том же порядке, в котором они произошли в таблице, для обновления последующих систем. DynamoDB Streams Поток DynamoDB отлично подходит для Rockset, позволяя оставаться в курсе событий таблицы DynamoDB практически в реальном времени, но это еще не все. Поток DynamoDB содержит только записи операций записи, которые произошли после включения потока в таблице. Кроме того, . Операции, произошедшие до включения потока или более 24 часов назад, не будут присутствовать в потоке. поток DynamoDB сохраняет записи только 24 часа Но Rockset нужны не только самые последние данные, но и все данные в вашей базе данных, чтобы правильно отвечать на ваши запросы. Чтобы справиться с этим, он выполняет первоначальный массовый экспорт (с использованием сканирования DynamoDB или , в зависимости от размера вашей таблицы), чтобы получить исходное состояние вашей таблицы. экспорта в S3 Таким образом, процесс подключения Rockset DynamoDB состоит из двух частей: Начальный процесс начальной для экспорта всей таблицы для обработки в Rockset; загрузки Последующий процесс получения обновлений из вашего потока DynamoDB и обновления данных в Rockset. непрерывный Обратите внимание, что оба этих процесса полностью управляются Rockset и прозрачны для вас как пользователя. Вы не будете отвечать за обслуживание этих конвейеров и реагирование на оповещения в случае возникновения ошибок. Кроме того, если вы выберете метод экспорта S3 для начального процесса приема, ни один из процессов приема Rockset не будет использовать единицы емкости чтения из вашей основной таблицы. Таким образом, Rockset не будет потреблять ресурсы из сценариев использования вашего приложения и не повлияет на доступность производства. Приложение: подключение DynamoDB к Rockset. Прежде чем перейти к использованию Rockset в нашем приложении, давайте подключим Rockset к нашей таблице DynamoDB. Во-первых, нам нужно создать новую интеграцию между Rockset и нашей таблицей. Ниже мы рассмотрим общие шаги, но при необходимости вы можете найти более . подробные пошаговые инструкции в репозитории приложения В консоли Rockset перейдите к , чтобы начать этот процесс. новому мастеру интеграции В мастере интеграции выберите в качестве типа интеграции. Затем нажмите , чтобы перейти к следующему шагу. Amazon DynamoDB «Пуск» Мастер интеграции DynamoDB содержит пошаговые инструкции по авторизации Rockset для доступа к вашей таблице DynamoDB. Для этого необходимо создать политику IAM, роль IAM и корзину S3 для экспорта таблицы. Если хотите, вы можете следовать этим инструкциям, чтобы создать ресурсы вручную. В бессерверном мире мы предпочитаем, насколько это возможно, создавать вещи с помощью , включая вспомогательные ресурсы. инфраструктуры как кода Репозиторий примера включает инфраструктуру в виде кода, необходимую для создания ресурсов интеграции Rockset. Чтобы использовать их, сначала найдите значения идентификатора учетной записи Rockset и внешнего идентификатора в нижней части мастера интеграции Rockset. Скопируйте и вставьте эти значения в файла serverless.yml. Затем чтобы создать эти ресурсы. соответствующие разделы пользовательского custom раскомментируйте ресурсы в строках с 71 по 122 файла serverless.yml, Повторно разверните приложение, чтобы создать эти новые ресурсы. В результатах развертывания скопируйте и вставьте имя корзины S3 и ARN роли IAM в соответствующие места консоли Rockset. Затем нажмите кнопку «Сохранить интеграцию», чтобы сохранить интеграцию. После того, как вы создали свою интеграцию, вам нужно будет создать на основе интеграции. Перейдите к в консоли Rockset и следуйте инструкциям, чтобы использовать интеграцию для создания коллекции. вы также можете найти в репозитории приложения. коллекцию Rockset мастеру создания коллекции Пошаговые инструкции по созданию коллекции После того как вы завершите это соединение, как правило, в наборе экземпляров надлежащего размера вставки, обновления или удаления данных в DynamoDB будут отражены в индексе Rockset и доступны для запроса менее чем за 2 секунды. Использование Rockset для сложной фильтрации Теперь, когда мы подключили Rockset к нашей таблице DynamoDB, давайте посмотрим, как Rockset может реализовать новые шаблоны доступа к нашим существующим данным. Напомним, что в разделе «Основные функции» DynamoDB уделяет большое внимание первичным ключам. Вы должны использовать свой первичный ключ для эффективного доступа к вашим данным. Соответственно, мы структурировали нашу таблицу так, чтобы в наших первичных ключах использовались название организации и время транзакции. Эта структура работает для наших основных шаблонов доступа, но мы можем захотеть предоставить пользователям более гибкий способ просмотра своих транзакций. Существует ряд полезных атрибутов — категория, название продавца, сумма и т. д. — которые могут оказаться полезными при фильтрации. Мы могли бы использовать вторичные индексы DynamoDB, чтобы включить фильтрацию по большему количеству атрибутов, но здесь это все равно не очень подходит. Структура первичного ключа DynamoDB не позволяет легко выполнять гибкие запросы, включающие комбинации множества необязательных атрибутов. У вас может быть вторичный индекс для фильтрации по названию продавца и дате, но вам понадобится еще один вторичный индекс, если вы хотите разрешить фильтрацию по названию продавца, дате и сумме. Для шаблона доступа с фильтрацией по категории потребуется третий вторичный индекс. Вместо того, чтобы разбираться с этой сложностью, мы здесь воспользуемся Rockset. Ранее мы видели, что Rockset использует конвергентный индекс для индексации ваших данных несколькими способами. Одним из таких способов является инвертированный индекс. При использовании инвертированного индекса Rockset напрямую индексирует каждый атрибут. Обратите внимание, как организован этот индекс. Каждое имя и значение атрибута используется в качестве ключа индекса, а значение представляет собой список идентификаторов документов, которые включают соответствующее имя и значение атрибута. Ключи сконструированы таким образом, что их естественный порядок сортировки может эффективно поддерживать запросы диапазона. Инвертированный индекс отлично подходит для запросов с выборочными условиями фильтрации. Представьте, что мы хотим позволить нашим пользователям фильтровать свои транзакции, чтобы найти те, которые соответствуют определенным критериям. Кто-то в организации Vandelay Industries интересуется, сколько раз они за последнее время заказывали Chipotle. Вы можете найти это с помощью следующего запроса: SELECT * FROM transactions WHERE organization = 'Vandelay Industries' AND merchant_name = 'Chipotle' Поскольку мы применяем выборочные фильтры по имени клиента и продавца, мы можем использовать инвертированный индекс для быстрого поиска совпадающих документов. Rockset будет искать пары имени и значения атрибута в инвертированном индексе, чтобы найти списки совпадающих документов. Получив эти два списка, он может объединить их, чтобы найти набор записей, соответствующих обоим наборам условий, и вернуть результаты обратно клиенту. Точно так же, как индексирование на основе разделов DynamoDB эффективно для операций, использующих ключ раздела, инвертированный индекс Rockset обеспечивает эффективный поиск по любому полю в вашем наборе данных, даже по атрибутам встроенных объектов или значениям внутри встроенных массивов. Приложение: использование Rockset API в вашем приложении. Теперь, когда мы знаем, как Rockset может эффективно выполнять выборочные запросы к нашему набору данных, давайте рассмотрим практические аспекты интеграции запросов Rockset в наше приложение. Rockset предоставляет сервисы RESTful, защищенные токеном авторизации. SDK также доступны для популярных языков программирования. Это делает его идеальным для интеграции с бессерверными приложениями, поскольку вам не нужно настраивать сложную конфигурацию частной сети для доступа к вашей базе данных. Чтобы взаимодействовать с Rockset API в нашем приложении, нам понадобится ключ Rockset API. Вы можете создать его в консоли Rockset. После этого скопируйте его значение в файл serverless.yml и повторно разверните его, чтобы сделать его доступным для вашего приложения. разделе ключей API Примечание: для простоты мы используем этот ключ API в качестве переменной среды. В реальном приложении вам следует использовать что-то вроде или , чтобы хранить свой секрет и избегать переменных среды. хранилища параметров AWS Secrets Manager Посмотрите на наш , чтобы увидеть, как мы взаимодействуем с API Rockset. Инициализация класса принимает клиентский объект Rockset, который будет использоваться для вызовов Rockset. класс TransactionService В у нас есть следующий запрос для взаимодействия с Rockset: методе filterTransactions нашего класса сервиса const response = await this._rocksetClient.queries.query({ sql: { query: ` SELECT * FROM Transactions WHERE organization = :organization AND category = :category AND amount BETWEEN :minAmount AND :maxAmount ORDER BY transactionTime DESC LIMIT 20`, parameters: [ { name: "organization", type: "string", value: organization, }, { name: "category", type: "string", value: category, }, { name: "minAmount", type: "float", value: minAmount, }, { name: "maxAmount", type: "float", value: maxAmount, }, ], }, }); В этом взаимодействии следует отметить две вещи. Во-первых, мы используем именованные параметры в нашем запросе при обработке ввода от пользователей. Это обычная практика для баз данных SQL, позволяющая избежать атак с использованием SQL-инъекций. Во-вторых, код SQL перемешан с кодом нашего приложения, и его сложно отслеживать с течением времени. Хотя это может сработать, есть способ получше. Применяя следующий вариант использования, мы рассмотрим, как использовать Rockset Query Lambdas в нашем приложении. Использование Rockset для агрегации К этому моменту мы рассмотрели стратегии индексирования DynamoDB и Rockset, обсуждая, как база данных может найти отдельную запись или набор записей, которые соответствуют определенному предикату фильтра. Например, мы видели, что DynamoDB подталкивает вас к использованию первичного ключа для поиска записи, тогда как инвертированный индекс Rockset может эффективно находить записи, используя условия высокоизбирательной фильтрации. В этом последнем разделе мы немного переключимся, чтобы сосредоточиться на размещении данных, а не на непосредственной индексации. Размышляя о расположении данных, мы противопоставим два подхода: на основе строк и на основе столбцов. Базы данных на основе строк, как следует из названия, размещают свои данные на диске в строках. Большинство реляционных баз данных, таких как PostgreSQL и MySQL, представляют собой базы данных на основе строк. То же самое можно сказать и о многих базах данных NoSQL, таких как DynamoDB, даже если их записи технически не являются «строками» в смысле реляционной базы данных. Базы данных на основе строк отлично подходят для шаблонов доступа, которые мы рассматривали до сих пор. При получении отдельной транзакции по ее идентификатору или набора транзакций в соответствии с некоторыми условиями фильтра мы обычно хотим, чтобы все поля возвращались для каждой транзакции. Поскольку все поля записи хранятся вместе, для возврата записи обычно требуется одно чтение. (Примечание: здесь есть некоторые нюансы). Агрегация – это совсем другая история. С помощью агрегирующих запросов мы хотим вычислить агрегат — количество всех транзакций, сумму общих транзакций или средние расходы по месяцам для набора транзакций. Возвращаясь к пользователю из организации Vandelay Industries, представьте, что он хочет просмотреть данные за последние три месяца и найти общие расходы по категориям за каждый месяц. Упрощенная версия этого запроса будет выглядеть следующим образом: SELECT category, EXTRACT(month FROM transactionTime) AS month, sum(amount) AS amount FROM transactions WHERE organization = 'Vandelay Industries' AND transactionTime > CURRENT_TIMESTAMP() - INTERVAL 3 MONTH GROUP BY category, month ORDER BY category, month DESC Для этого запроса может существовать большое количество записей, которые необходимо прочитать для вычисления результата. Однако обратите внимание, что нам не нужно много полей для каждой из наших записей. Нам нужно всего четыре — категория, время транзакции, организация и сумма — чтобы определить этот результат. Таким образом, нам не только нужно прочитать гораздо больше записей, чтобы удовлетворить этот запрос, но и наш макет на основе строк будет читать кучу полей, которые не нужны для нашего результата. И наоборот, макет на основе столбцов хранит данные на диске в столбцах. Конвергентный индекс Rockset использует столбчатый индекс для хранения данных в виде столбцов. В макете на основе столбцов данные хранятся вместе по столбцам. Отдельная запись разбивается на составляющие ее столбцы для индексации. Если моему запросу необходимо выполнить агрегацию для суммирования атрибута «сумма» для большого количества записей, Rockset может сделать это, просто просканировав часть «суммы» столбцового индекса. Это значительно уменьшает объем считываемых и обрабатываемых данных по сравнению с макетами на основе строк. Обратите внимание, что по умолчанию столбчатый индекс Rockset не упорядочивает атрибуты внутри столбца. Поскольку у нас есть варианты использования, ориентированные на пользователя, которые будут работать с данными конкретного клиента, мы бы предпочли организовать наш столбчатый индекс по клиентам, чтобы уменьшить объем данных для сканирования при использовании столбчатого индекса. Rockset обеспечивает , чтобы помочь в этом. С помощью кластеризации мы можем указать, что хотим, чтобы наш столбчатый индекс был кластеризован по атрибуту «организация». Это сгруппирует все значения столбцов по организации в столбцовых индексах. Таким образом, когда Vandelay Industries выполняет агрегирование своих данных, процессор запросов Rockset может пропускать части столбчатого индекса для других клиентов. кластеризацию данных в вашем столбчатом индексе Как строковый индекс Rockset помогает в обработке Прежде чем мы перейдем к использованию столбчатого индекса в нашем приложении, я хочу поговорить о другом аспекте конвергентного индекса Rockset. Ранее я упоминал, что при извлечении полных записей использовались макеты на основе строк, и указывал, что и DynamoDB, и наши запросы с инвертированным индексом Rockset использовали эти макеты. Это правда лишь отчасти. Инвертированный индекс имеет некоторое сходство с индексом на основе столбцов, поскольку в нем имена и значения столбцов хранятся вместе для эффективного поиска по любому атрибуту. Каждая запись индекса включает указатель на идентификаторы записей, которые включают данное имя столбца и комбинацию значений. Как только соответствующий идентификатор или идентификаторы будут обнаружены из инвертированного индекса, Rockset сможет получить полную запись, используя индекс строки. Rockset использует словарное кодирование и другие передовые методы сжатия, чтобы минимизировать размер хранилища данных. Таким образом, мы теперь увидели, как сочетается конвергентный индекс Rockset: используется для быстрого сканирования большого количества значений в определенном столбце на предмет агрегирования; Индекс на основе столбцов используется для выборочных фильтров по любому имени и значению столбца; Инвертированный индекс используется для извлечения любых дополнительных атрибутов, на которые можно ссылаться в предложении проекции. Индекс на основе строк Под капотом мощный механизм индексирования и запросов Rockset отслеживает статистику ваших данных и создает оптимальные планы для эффективного выполнения вашего запроса. Приложение: использование лямбда-выражений Rockset Query в вашем приложении. Давайте реализуем наш агрегирующий запрос Rockset, использующий столбчатый индекс. Для нашего предыдущего запроса мы написали SQL-запрос непосредственно в Rockset API. Хотя это и правильно для некоторых легко настраиваемых пользовательских интерфейсов, есть лучший вариант, когда код SQL более статичен. Мы хотели бы избежать хранения нашего беспорядочного кода SQL в середине логики нашего приложения. Чтобы помочь в этом, в Rockset есть функция под названием Query Lambdas. Лямбды запросов — это именованные, версионные, параметризованные запросы, которые регистрируются в консоли Rockset. После того, как вы настроили лямбду запроса в Rockset, вы получите полностью управляемую масштабируемую конечную точку для лямбды запроса, которую вы можете вызывать с вашими параметрами для выполнения Rockset. Кроме того, вы даже получите статистику мониторинга для каждой лямбды запроса, чтобы вы могли отслеживать, как работает ваша лямбда запроса при внесении изменений. Вы можете , но давайте настроим нашу первую лямбду-запрос для обработки нашего запроса агрегации. . узнать больше о лямбда-выражениях запроса здесь Полное прохождение можно найти в репозитории приложения Перейдите в консоли Rockset. Вставьте следующий запрос в редактор: раздел «Редактор запросов» SELECT category, EXTRACT( month FROM transactionTime ) as month, EXTRACT( year FROM transactionTime ) as year, TRUNCATE(sum(amount), 2) AS amount FROM Transactions WHERE organization = :organization AND transactionTime > CURRENT_TIMESTAMP() - INTERVAL 3 MONTH GROUP BY category, month, year ORDER BY category, month, year DESC Этот запрос группирует транзакции за последние три месяца для данной организации в сегменты на основе заданной категории и месяца транзакции. Затем он суммирует значения по категориям по месяцам, чтобы найти общую сумму, потраченную в течение каждого месяца. Обратите внимание, что он включает параметр для атрибута «organization», как указано в синтаксисе «:organization» в запросе. Это указывает на то, что для выполнения запроса необходимо передать значение организации. Сохраните запрос как Query Lambda в консоли Rockset. Затем посмотрите на . Он вызывает лямбда-запрос по имени и передает свойство «организация», предоставленное пользователем. код fetchTransactionsByCategoryAndMonth в нашем классе TransactionService Этот код гораздо проще обрабатывать в нашем приложении. Кроме того, Rockset обеспечивает контроль версий и мониторинг каждого запроса для каждого лямбда-запроса. Это упрощает поддержку ваших запросов с течением времени и позволяет понять, как изменения в синтаксисе запросов влияют на производительность. Заключение В этом посте мы увидели, как использовать DynamoDB и Rockset вместе, чтобы создать быстрое и приятное приложение для наших пользователей. При этом мы изучили как концептуальные основы, так и практические шаги по реализации нашего приложения. Сначала мы использовали DynamoDB для реализации основных функций нашего приложения. Сюда входят шаблоны доступа, такие как получение ленты транзакций для конкретного клиента или просмотр отдельной транзакции. Благодаря стратегии секционирования DynamoDB на основе первичного ключа она способна обеспечить стабильную производительность в любом масштабе. Но конструкция DynamoDB также ограничивает ее гибкость. Он не может обрабатывать выборочные запросы к произвольным полям или агрегатам по большому количеству записей. Для обработки этих шаблонов мы использовали Rockset. Rockset предоставляет полностью управляемый вторичный индекс для работы приложений с большим объемом данных. Мы увидели, как Rockset поддерживает непрерывный конвейер приема данных из вашего основного хранилища данных, который индексирует ваши данные в конвергентном индексе, который сочетает в себе инвертированную, столбчатую и строковую индексацию. Изучая наши шаблоны, мы увидели, как каждый из методов индексирования Rockset работает вместе, обеспечивая приятный пользовательский опыт. Наконец, мы выполнили практические шаги по подключению Rockset к нашей таблице DynamoDB и взаимодействию с Rockset в нашем приложении. Также появляется . здесь