Смотрите, отличие в используемых структурах данных, в первом случае это Lua-table, которая создавалась для хранения любых типов данных и делает дополнительные проверки на типы, что получается более медленно, чем второй вариант:
for i = 1, 1000 do
local v = tuple.data[i] -- чтение поля таблицы
if v.name == 'name' then -- чтение поля таблицы
v.value = v.value + 1 -- чтение поля таблицы
end
tuple.data[i] = v -- запись поля таблицы
end
Во втором случае это обращение к полю структуры Tarantool tuple, который оптимизирован для получения данных с учетом формата + мы обходим данные по отдельному индексу:
for _, v in box.space.storage2:pairs({'key'}) do
if v.name == 'name' then -- чтения поля тапла
box.space.storage2:update({v.key, v.pos}, {{'+', 'value', 1}}) -- запись в тапл
end
end
Возможно, здесь еще сыграет роль объем данных (в первом случае мы должны перезаписать весь массив из 1000 элементов, во втором - только те элементы "массива", которые поменялись, но это не точно, можно побенчить.
В Tarantool однопоточный асинхронный менеджер транзакций (запросов). Запросы выполняются в файберах (аналог корутин) — кооперативно. То есть в один момент времени выполняется только один запрос. Запрос select(nil) выполняется от начала и до конца — не выполняя прерываний и передачи управления другим запросам. Исторически это было сделано для того, чтобы в момент запроса к данным, не выполнялся другой запрос, который может эти данные перезаписать.
Да, действительно, хранить разные сущности в одной таблице - плохой подход.
Но на самом деле код не сильно усложнится, если добавить несколько сущностей и делать "join" этих данных.
Один из вариантов примерной реализации:
-- в роли storage:
local employee = box.schema.space.create('employee', {if_not_exists = true}
employee:format(...)
-- добавляем новые спейсы, форматы и индексы
local department = box.schema.space.create('department', {if_not_exists = true}
department:format(...)
---------------------------------
-- в роле api:
local employees, err = crud.select('employee', {{'>=', 'salary', salary}})
-- получаем список отделов по названиям
local department = {}
for _, x in ipairs(employees) do
if department[x.department] ~= nil then
local dep, err = crud.get('department', department)
department[dep.name] = dep
end
end
-- возвращаем employee join department
employees = fun.iter(employees):map(function(x)
return {
employee_id = x.employee_id,
...
salary = x.salary,
department_data = department[x.department],
}
end):totable()
Да, можно в общем случае. Но в алгоритме Summary-коллектора еще происходит сжатие данных, а quicksort там используется не для поиска перцентилей, а для того, чтобы отсортировать буфер перед тем, как «влить» его в массив наблюдений, который затем можно будет сжимать.
По задумке Summary-коллектора, расчет перцентилей отдается на сторону клиентов Prometheus'a, а он собирает уже посчитанные значения. Перцентили в Prometheus можно посчитать только для Histogram-коллектора.
Зависит от вставляемых данных (порядок, разброс значений). Последняя итерация делала в среднем 3млн вставок в секунду для рандомных данных от 0 до 100.
В Tarantool есть mvcc, подробнее можно здесь почитать: https://www.tarantool.io/ru/doc/latest/book/box/atomic/transaction_model/#isolation-level
Смотрите, отличие в используемых структурах данных, в первом случае это Lua-table, которая создавалась для хранения любых типов данных и делает дополнительные проверки на типы, что получается более медленно, чем второй вариант:
Во втором случае это обращение к полю структуры Tarantool tuple, который оптимизирован для получения данных с учетом формата + мы обходим данные по отдельному индексу:
Возможно, здесь еще сыграет роль объем данных (в первом случае мы должны перезаписать весь массив из 1000 элементов, во втором - только те элементы "массива", которые поменялись, но это не точно, можно побенчить.
Про Луа таблицы можно почитать здесь: https://habr.com/ru/company/vk/blog/493642/
Про индексы - здесь: https://habr.com/ru/company/vk/blog/505880/
Ну и вообще можно еще сюда посмотреть, тут пример того, как мы отказались от Lua-таблиц в пользу C structure: https://habr.com/ru/company/vk/blog/529456/
В Tarantool однопоточный асинхронный менеджер транзакций (запросов). Запросы выполняются в файберах (аналог корутин) — кооперативно. То есть в один момент времени выполняется только один запрос. Запрос select(nil) выполняется от начала и до конца — не выполняя прерываний и передачи управления другим запросам. Исторически это было сделано для того, чтобы в момент запроса к данным, не выполнялся другой запрос, который может эти данные перезаписать.
Да, действительно, хранить разные сущности в одной таблице - плохой подход.
Но на самом деле код не сильно усложнится, если добавить несколько сущностей и делать "join" этих данных.
Один из вариантов примерной реализации:
unique = false
. www.tarantool.io/ru/doc/latest/reference/reference_lua/box_space/create_indexВ тарантуле для прохода по всем записям можно сделать — это вернет итератор по всем записям, потом с ним можно будет работать с помощью luafun.github.io. Не используйте или без ограничения на количество элементов в или без вызова через N итераций — это гарантированный способ уронить себе прод, особенно если у вас большой объем данных.
Нет, не каждая, внутри коллектора буфер на 500 элементов, по заполнению он сортируется и вставляется в массив наблюдений.