История изменений
Исправление trisobakov, (текущая версия) :
На самом деле список не нужен. Держим все реакции как строку интов в колонке likes
(вместо одного 8-битного инта, который там щас лежит). 03010007000800
- это вектор размера 3 (первый байт) - (1,7,8)
. Больше чем страница B+-Tree этот вектор не раздует в любом случае (так что 8-битная длина этого вектора - годнота), иначе это уже изврат (мессага, у которой больше 255 РАЗНЫХ реакций - это боль и «ненужно» даже визуально).
То есть, сохранить вектор интов вида (11, 501, 800, 804) (естественно в бинарном виде, где инт 16-битен) в самой сообщеньке в отдельной колонке и читать это в составе сообщеньки - вполне годнота.
То есть, реальна реализация, в которой чтение 10 сообщенек - это вообще 1 чтение. Сообщеньки-то лежат физически друг за другом в одном блоке B+-Tree, и в каждой из них свой вектор вида (300, 303, 308). То есть, выгребание поддиапазона сообщенек треда, учитывая, что тред - это key=list<message>
- это вообще последовательное чтение куска памяти, т.к. участка одного блока, т.е. даже с диска это будет 1 чтение. Всё отлично.
Как апдейтить: если сервис лайков, куда я запихнул реакцию типа 501 (лицо Обамы «Not Bad») сказал, что этой сообщеньке эту реакцию я поставил первым, ТОГДА пойти и проапдейтить колонку likes
сообщеньки - достать оттуда вектор интов, добавить 501, положить обратно. Можно CAS-ом в цикле, чтобы 501 не пролюбить. В целом, этих апдейтов будет мало - по числу уникальных реакций. Получние 1000 сердечек и 2000 Обам - это таких 2 апдейта.
Всё красиво, но я нагнал слегка.
Нам ещё нужно узнать чиселку у каждой реакции. Поэтому, каждая сообщенька породит N запросов, где N - длина вектора из колонки likes
. Допустим, если чатик называется hello
, id сообщеньки - 13444, а её likes
- это (1,7,8)
, то в сервис лайков нам надо отправить 3 запроса len("hello:13444:1")
, len("hello:13444:7")
, len("hello:13444:8")
.
На прочие вопросы
Зачем NoSQL
Важно что там внутри физически и за что ты хочешь платить. Если у тебя в MySQL табличка из 2 колонок (key,value)
, первичный и единственный индекс по key
и движок InnoDB
то на диске ты имеешь то же самое и столько же чтений с диска при доступк к ключу, что будет в не-MySQL-опердени, которая использует B+-Tree для key-value. Дальше начинаются низкоуровневые детали, «исторически сложилось».
Зачем ковыряться в битах.
Причина - пошлое грязное бабло и user experience. Скажем, ранний VK работал в штатах быстрее FB, а современная телега не тормозит при 100500 нагрузки в неё во все дыры как раз из-за этого байтоёбства. Код, который физически хранит в телеге ваши мессаги читать без крови из глаз вы тоже не сможете, но всем насрать на страдания полутора несчастных рабов в серверных, как пассажирам титаника было похер на жару в машинном зале (и затонул он не поэтому), важно как быстро телега открывается, сколько пассажиров на борту и сколько дисков Дурову нужно купить в сервера, сколько канала сожрать на клиентов и на бекапы в соседний ДЦ. В результате байтоёбства расход этих бездуховных денег сокращается и тупо продлевает жизнь проекта, что уже прямо политика и бизнес. Как говорил мужик в красной рубашке на 1:18:00 на этом видосе https://www.youtube.com/watch?v=rX0ItVEVjHc - люди, которым пофиг как долго сортируется список - причина того, что у меня ворд в винде по 30 секунд запускается! Так что не будем наезжать на байтоёбство, оно нужно и важно, просто не для всех. Так же, как не все люди проходят отбор в Navy SEAL в США - чё теперь, запретить их.
Исправление trisobakov, :
На самом деле список не нужен. Держим все реакции как строку интов в колонке likes
(вместо одного 8-битного инта, который там щас лежит). 03010007000800
- это вектор размера 3 (первый байт) - (1,7,8)
. Больше чем страница B+-Tree этот вектор не раздует в любом случае (так что 8-битная длина этого вектора - годнота), иначе это уже изврат (мессага, у которой больше 255 РАЗНЫХ реакций - это боль и «ненужно» даже визуально).
То есть, сохранить вектор интов вида (11, 501, 800, 804) (естественно в бинарном виде, где инт 16-битен) в самой сообщеньке в отдельной колонке и читать это в составе сообщеньки - вполне годнота.
То есть, реальна реализация, в которой чтение 10 сообщенек - это вообще 1 чтение. Сообщеньки-то лежат физически друг за другом в одном блоке B+-Tree, и в каждой из них свой вектор вида (300, 303, 308). То есть, выгребание поддиапазона сообщенек треда, учитывая, что тред - это key=list<message>
- это вообще последовательное чтение куска памяти, т.к. участка одного блока, т.е. даже с диска это будет 1 чтение. Всё отлично.
Как апдейтить: если сервис лайков, куда я запихнул реакцию типа 501 (лицо Обамы «Not Bad») сказал, что этой сообщеньке эту реакцию я поставил первым, ТОГДА пойти и проапдейтить колонку likes
сообщеньки - достать оттуда вектор интов, добавить 501, положить обратно. Можно CAS-ом в цикле, чтобы 501 не пролюбить. В целом, этих апдейтов будет мало - по числу уникальных реакций. Получние 1000 сердечек и 2000 Обам - это таких 2 апдейта.
Всё красиво, но я нагнал слегка.
Нам ещё нужно узнать чиселку у каждой реакции. Поэтому, каждая сообщенька породит N запросов, где N - длина вектора из колонки likes
. Допустим, если чатик называется hello
, id сообщеньки - 13444, а её likes
- это (1,7,8)
, то в сервис лайков нам надо отправить 3 запроса len("hello:13444:1")
, len("hello:13444:7")
, len("hello:13444:8")
.
Исправление trisobakov, :
На самом деле список не нужен. Держим все реакции как строка интов в колонке likes
(вместо одного 8-битного инта, который там щас лежит). 03010007000800
- это вектор размера 3 (первый байт) - (1,7,8)
. Больше чем страница B+-Tree этот вектор не раздует в любом случае (так что 8-битная длина этого вектора - годнота), иначе это уже изврат (мессага, у которой больше 255 РАЗНЫХ реакций - это боль и «ненужно» даже визуально).
То есть, сохранить вектор интов вида (11, 501, 800, 804) (естественно в бинарном виде, где инт 16-битен) в самой сообщеньке в отдельной колонке и читать это в составе сообщеньки - вполне годнота.
То есть, реальна реализация, в которой чтение 10 сообщенек - это вообще 1 чтение. Сообщеньки-то лежат физически друг за другом в одном блоке B+-Tree, и в каждой из них свой вектор вида (300, 303, 308). То есть, выгребание поддиапазона сообщенек треда, учитывая, что тред - это key=list<message>
- это вообще последовательное чтение куска памяти, т.к. участка одного блока, т.е. даже с диска это будет 1 чтение. Всё отлично.
Как апдейтить: если сервис лайков, куда я запихнул реакцию типа 501 (лицо Обамы «Not Bad») сказал, что этой сообщеньке эту реакцию я поставил первым, ТОГДА пойти и проапдейтить колонку likes
сообщеньки - достать оттуда вектор интов, добавить 501, положить обратно. Можно CAS-ом в цикле, чтобы 501 не пролюбить. В целом, этих апдейтов будет мало - по числу уникальных реакций. Получние 1000 сердечек и 2000 Обам - это таких 2 апдейта.
Исправление trisobakov, :
На самом деле список не нужен. Держим все реакции как строка интов в колонке likes
(вместо одного 8-битного инта, который там щас лежит). 03010007000800
- это вектор размера 3 (первый байт) - (1,7,8)
. Больше чем страница B+-Tree этот вектор не раздует в любом случае (так что 8-битная длина этого вектора - годнота), иначе это уже изврат (мессага, у которой 100500 РАЗНЫХ реакций - это боль и «ненужно» даже визуально).
То есть, сохранить вектор интов вида (11, 501, 800, 804) (естественно в бинарном виде, где инт 16-битен) в самой сообщеньке в отдельной колонке и читать это в составе сообщеньки - вполне годнота.
То есть, реальна реализация, в которой чтение 10 сообщенек - это вообще 1 чтение. Сообщеньки-то лежат физически друг за другом в одном блоке B+-Tree, и в каждой из них свой вектор вида (300, 303, 308). То есть, выгребание поддиапазона сообщенек треда, учитывая, что тред - это key=list<message>
- это вообще последовательное чтение куска памяти, т.к. участка одного блока, т.е. даже с диска это будет 1 чтение. Всё отлично.
Как апдейтить: если сервис лайков, куда я запихнул реакцию типа 501 (лицо Обамы «Not Bad») сказал, что этой сообщеньке эту реакцию я поставил первым, ТОГДА пойти и проапдейтить колонку likes
сообщеньки - достать оттуда вектор интов, добавить 501, положить обратно. Можно CAS-ом в цикле, чтобы 501 не пролюбить. В целом, этих апдейтов будет мало - по числу уникальных реакций. Получние 1000 сердечек и 2000 Обам - это таких 2 апдейта.
Исправление trisobakov, :
На самом деле список не нужен. Держим все реакции как строка интов в колонке likes
(вместо одного 8-битного инта, который там щас лежит). 03010007000800
- это вектор размера 3 (первый байт) - (1,7,8)
. Больше чем страница B+-Tree этот вектор не раздует всё равно, иначе это уже изврат (мессага, у которой 100500 РАЗНЫХ реакций - это боль и «ненужно» даже визуально).
То есть, сохранить вектор интов вида (11, 501, 800, 804) (естественно в бинарном виде, где инт 16-битен) в самой сообщеньке в отдельной колонке и читать это в составе сообщеньки - вполне годнота.
То есть, реальна реализация, в которой чтение 10 сообщенек - это вообще 1 чтение. Сообщеньки-то лежат физически друг за другом в одном блоке B+-Tree, и в каждой из них свой вектор вида (300, 303, 308). То есть, выгребание поддиапазона сообщенек треда, учитывая, что тред - это key=list<message>
- это вообще последовательное чтение куска памяти, т.к. участка одного блока, т.е. даже с диска это будет 1 чтение. Всё отлично.
Как апдейтить: если сервис лайков, куда я запихнул реакцию типа 501 (лицо Обамы «Not Bad») сказал, что этой сообщеньке эту реакцию я поставил первым, ТОГДА пойти и проапдейтить колонку likes
сообщеньки - достать оттуда вектор интов, добавить 501, положить обратно. Можно CAS-ом в цикле, чтобы 501 не пролюбить. В целом, этих апдейтов будет мало - по числу уникальных реакций. Получние 1000 сердечек и 2000 Обам - это таких 2 апдейта.
Исходная версия trisobakov, :
На самом деле список не нужен. Держим все реакции как строка интов в колонке likes
(вместо одного 8-битного инта, который там щас лежит). Больше чем страница B+-Tree этот вектор не раздует всё равно, иначе это уже изврат (мессага, у которой 100500 РАЗНЫХ реакций - это боль и «ненужно» даже визуально).
То есть, сохранить вектор интов вида (11, 501, 800, 804) (естественно в бинарном виде, где инт 16-битен) в самой сообщеньке в отдельной колонке и читать это в составе сообщеньки - вполне годнота.
То есть, реальна реализация, в которой чтение 10 сообщенек - это вообще 1 чтение. Сообщеньки-то лежат физически друг за другом в одном блоке B+-Tree, и в каждой из них свой вектор вида (300, 303, 308). То есть, выгребание поддиапазона сообщенек треда, учитывая, что тред - это key=list<message>
- это вообще последовательное чтение куска памяти, т.к. участка одного блока, т.е. даже с диска это будет 1 чтение. Всё отлично.
Как апдейтить: если сервис лайков, куда я запихнул реакцию типа 501 (лицо Обамы «Not Bad») сказал, что этой сообщеньке эту реакцию я поставил первым, ТОГДА пойти и проапдейтить колонку likes
сообщеньки - достать оттуда вектор интов, добавить 501, положить обратно. Можно CAS-ом в цикле, чтобы 501 не пролюбить. В целом, этих апдейтов будет мало - по числу уникальных реакций. Получние 1000 сердечек и 2000 Обам - это таких 2 апдейта.