Notice: file_put_contents(): Write of 20400 bytes failed with errno=28 No space left on device in /var/www/tgoop/post.php on line 50
Эшу быдлокодит@eshu_coding P.288
ESHU_CODING Telegram 288
Получил лвлап и кучу экспириенса по работе с тарантулом, что характерно - на ровном месте.

Рассмотрим кейс: есть некая запись, относящаяся к человеку (user_id, unsigned(UInt64)). У нее есть время создания (creation_time, integer (Int64)) и время закрытия (cancelled_at, integer (Int64)).

Нужно дёрнуть все записи, относящиеся к человеку, актуальные на определенный момент времени. То есть запрос вида:
Входящие параметры: id, time.
user_id == id && creation_time <= time && (cancelled_at == nil || cancelled_at >= time)

Во всех мануалах предлагается простое решение, сделать select по самому лучшему условию, а дальше с помощью специального синтаксиса перебрать результат и отфильтровать нужное. Использовал этот подход, решил задачу и пошел дальше.
И все было прекрасно, пока я не столкнулся с реальностью: на "жирном" пользователе, с 20к+ записей, запрос выполняется неадекватные 20+ секунд.

В тарантуле есть составные индексы, туда можно передавать запросы из нескольких частей. Но вот беда: запрос, объединяющий сравнения == <= и >= он выполнить не может.
Решил зайти с необычной стороны: сделать условием >= и построить следующий индекс: creation_time, user_id, - user_id, - cancellation_time

То есть добавить в индекс инвертированный id пользователя и инвертировать время закрытия. Тогда в теории все должно выцепляться одним условием ">=". Что могло пойти не так? Всё. Как оказалось, для составных условий используется логика обработки частей запроса, отличающаяся от той, что заложена в схожей ситуации в MongoDB или PostgreSQL.
Сравнение происходит не по частям индекса. В сравнении участвует весь массив целиком как единая сущность. Говорят, что логика сравнения где-то была описана, но с ходу страница документации не ищется и где она лежит никто не помнит.

В тарантуле есть специальный инструментарий для работы с пространственными данными. Казалось бы, при чём тут они?
Поднимемся по лестнице абстракций на пару ступеней. Представим себе запись о пользователе прямоугольником в системе координат (id пользователя/время). Одна точка прямоугольника - создание записи, имеет координаты (user_id, creation_time). Вторая - (user_id, cancelled_at).
Соответственно, проверка "существовала ли запись о пользователе в определенный момент времени"? Сводится к задаче о принадлежности точки прямоугольнику. Готовое решение для запроса по индексу - в наличии. При желании, можно добавить ещё измерений (до 20), но что-то пока не хочется.

Проблема решена? Фииигушки. Индекс не ест мои значения в Int64 и UInt64, ему подавай Float64. При ковертации "в лоб" хвостики id теряются, из-за ограничений точности Float64. Добавляем очередной велосипед.

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

А вот теперь - всё. Ну или мне так кажется:)

P.S. В монге решил эту же задачу за 25 (!) минут, запрос + индексы, всё работает с первого раза.

#tarantool
🔥4🤡2



tgoop.com/eshu_coding/288
Create:
Last Update:

Получил лвлап и кучу экспириенса по работе с тарантулом, что характерно - на ровном месте.

Рассмотрим кейс: есть некая запись, относящаяся к человеку (user_id, unsigned(UInt64)). У нее есть время создания (creation_time, integer (Int64)) и время закрытия (cancelled_at, integer (Int64)).

Нужно дёрнуть все записи, относящиеся к человеку, актуальные на определенный момент времени. То есть запрос вида:
Входящие параметры: id, time.
user_id == id && creation_time <= time && (cancelled_at == nil || cancelled_at >= time)

Во всех мануалах предлагается простое решение, сделать select по самому лучшему условию, а дальше с помощью специального синтаксиса перебрать результат и отфильтровать нужное. Использовал этот подход, решил задачу и пошел дальше.
И все было прекрасно, пока я не столкнулся с реальностью: на "жирном" пользователе, с 20к+ записей, запрос выполняется неадекватные 20+ секунд.

В тарантуле есть составные индексы, туда можно передавать запросы из нескольких частей. Но вот беда: запрос, объединяющий сравнения == <= и >= он выполнить не может.
Решил зайти с необычной стороны: сделать условием >= и построить следующий индекс: creation_time, user_id, - user_id, - cancellation_time

То есть добавить в индекс инвертированный id пользователя и инвертировать время закрытия. Тогда в теории все должно выцепляться одним условием ">=". Что могло пойти не так? Всё. Как оказалось, для составных условий используется логика обработки частей запроса, отличающаяся от той, что заложена в схожей ситуации в MongoDB или PostgreSQL.
Сравнение происходит не по частям индекса. В сравнении участвует весь массив целиком как единая сущность. Говорят, что логика сравнения где-то была описана, но с ходу страница документации не ищется и где она лежит никто не помнит.

В тарантуле есть специальный инструментарий для работы с пространственными данными. Казалось бы, при чём тут они?
Поднимемся по лестнице абстракций на пару ступеней. Представим себе запись о пользователе прямоугольником в системе координат (id пользователя/время). Одна точка прямоугольника - создание записи, имеет координаты (user_id, creation_time). Вторая - (user_id, cancelled_at).
Соответственно, проверка "существовала ли запись о пользователе в определенный момент времени"? Сводится к задаче о принадлежности точки прямоугольнику. Готовое решение для запроса по индексу - в наличии. При желании, можно добавить ещё измерений (до 20), но что-то пока не хочется.

Проблема решена? Фииигушки. Индекс не ест мои значения в Int64 и UInt64, ему подавай Float64. При ковертации "в лоб" хвостики id теряются, из-за ограничений точности Float64. Добавляем очередной велосипед.

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

А вот теперь - всё. Ну или мне так кажется:)

P.S. В монге решил эту же задачу за 25 (!) минут, запрос + индексы, всё работает с первого раза.

#tarantool

BY Эшу быдлокодит


Share with your friend now:
tgoop.com/eshu_coding/288

View MORE
Open in Telegram


Telegram News

Date: |

Add the logo from your device. Adjust the visible area of your image. Congratulations! Now your Telegram channel has a face Click “Save”.! The visual aspect of channels is very critical. In fact, design is the first thing that a potential subscriber pays attention to, even though unconsciously. A new window will come up. Enter your channel name and bio. (See the character limits above.) Click “Create.” Image: Telegram. Hui said the messages, which included urging the disruption of airport operations, were attempts to incite followers to make use of poisonous, corrosive or flammable substances to vandalize police vehicles, and also called on others to make weapons to harm police.
from us


Telegram Эшу быдлокодит
FROM American