Побитовые операции MySQL, фильтр Блума

Я хотел бы реализовать фильтр цветения с использованием MySQL (другая предлагаемая альтернатива).

Проблема в следующем:

Предположим, у меня есть таблица, в которой хранятся 8-битные целые числа со следующими значениями:

1: 10011010
2: 00110101
3: 10010100
4: 00100110
5: 00111011
6: 01101010

Я хотел бы найти все результаты побитовые И к этому:

00011000

Результатом должны быть строки 1 и 5.

Однако в моей проблеме это не 8-битные целые числа, а скорее n-битные целые числа. Как мне это сохранить и как сделать запрос? Скорость - ключ к успеху.

Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
9
0
14 567
6

Ответы 6

Создайте таблицу со столбцом int (используйте эта ссылка, чтобы выбрать правильный размер int). Не храните числа как последовательность 0 и 1.

Для ваших данных это будет выглядеть так:

number

154
53
148
38
59
106

и вам нужно найти все записи, соответствующие 24.

Затем вы можете запустить такой запрос, как

SELECT * FROM test WHERE number & 24 = 24

Если вы хотите избежать преобразования в 10 базовых чисел в своем приложении, вы можете передать его в mysql:

INSERT INTO test SET number = b'00110101';

и ищи вот так

SELECT bin(number) FROM test WHERE number & b'00011000' = b'00011000'

Спасибо за совет по запросу. Однако что мне делать, если я хочу хранить «n-битные» числа, которые длиннее, чем целые числа (32 бита) ... например, 64 или 128 бит?

Sam 12.12.2008 01:09

Тип данных Mysql BIT, похоже, поддерживает до 64 бит. Означает ли это, что в фильтре цветения можно хранить только 64 элемента?

Alexei Tenitski 12.12.2008 05:11

Мне нужно иметь возможность хранить n бит ... это ограничивает меня до 64.

Sam 16.12.2008 11:24

Предлагаемый ответ будет повторяться по ВСЕМ строкам в таблице. Это противоречит основному вопросу: «Скорость - ключ к успеху».

Dzmitry Lazerka 30.05.2017 03:55

Не используйте для этого MySQL.

Во-первых, вероятно, нет встроенного способа для более чем 64-битных таблиц. Вам придется прибегнуть к пользовательским функциям, написанным на C.

Во-вторых, каждый запрос потребует полного сканирования таблицы, потому что MySQL не может использовать индекс для вашего запроса. Так что, если ваш стол не очень маленький, это не будет быстро.

Это уход от вопроса, а не ответа.

Pacerier 20.10.2014 00:57

Переключитесь на PostgreSQL и используйте бит (n)

Фильтры Блума по своей природе требуют сканирования таблиц для оценки совпадений. В MySQL нет типа фильтра Блума. Простое решение - отобразить байты фильтра Блума на BitInteger (8-байтовые слова) и выполнить проверку в запросе. Итак, предполагая, что bloom фильтрует 8 байтов или меньше (очень маленький фильтр), вы можете выполнить подготовленный оператор, например:

SELECT * FROM test WHERE cast(filter, UNSIGNED) & cast(?, UNSIGNED) = cast(?, UNSIGNED)

и замените параметры на значение, которое вы ищете. Однако для более крупных фильтров вам необходимо создать несколько столбцов filter и разбить целевой фильтр на несколько слов. Вы должны привести к беззнаковому, чтобы выполнить проверку должным образом.

Поскольку многие разумные фильтры цветения имеют размер от килобайта до мегабайта, имеет смысл использовать капли для их хранения. После переключения на большие двоичные объекты не существует собственных механизмов для сравнения на уровне байтов. И тянуть целую таблицу больших двоичных объектов по сети, чтобы выполнить фильтр в коде локально, не имеет особого смысла.

Единственное разумное решение, которое я нашел, - это UDF. UDF должен принять char* и перебрать его, преобразовав char* в unsigned char*, и выполнить проверку target & candidate = target. Этот код будет выглядеть примерно так:

my_bool bloommatch(UDF_INIT *initid, UDF_ARGS *args, char* result, unsigned long* length, char *is_null, char *error)
{
    if (args->lengths[0] > args->lengths[1])
    {
        return 0;
    }
    char* b1=args->args[0];
    char* b2=args->args[1];
    int limit = args->lengths[0];
    unsigned char a;
    unsigned char b;
    int i;
    for (i=0;i<limit;i++)
    {
        a = (unsigned char) b1[i];
        b = (unsigned char) b2[i];
        if ((a & b) != a)
        {
            return 0;
        }
    }
    return 1;
}

Это решение реализовано и доступно здесь

Для до 64 бит вы можете использовать целочисленный тип MySQL, например tinyint (8b), int (16b), mediumint (24b) и bigint (64b). Используйте беззнаковые варианты.

Выше 64b используйте тип MySQL (VAR) BINARY. Это буферы необработанных байтов. Например, BINARY (16) подходит для 128 бит.

Чтобы предотвратить сканирование таблицы, вам нужен индекс для каждого полезного бита и / или индекс для набора связанных битов. Вы можете создать для этого виртуальные столбцы и поставить индекс для каждого из них.

Чтобы реализовать фильтр Блума с использованием базы данных, я бы подумал по-другому.

Я бы сделал двухуровневый фильтр. Используйте одну многобитную хеш-функцию для генерации идентификатора (это больше похоже на индекс корзины хеш-таблицы), а затем используйте биты в строке для оставшихся k-1 хеш-функций более классического типа. Внутри строки это может быть (скажем) 100 столбцов bigint (я бы также сравнил производительность с большими двоичными объектами).

Фактически это будет N отдельных фильтров Блума, где N - домен вашей первой хеш-функции. Идея состоит в том, чтобы уменьшить размер требуемого фильтра Блума, выбрав хеш-бакет. Он не обладал бы полной эффективностью фильтра Блума в памяти, но все же мог бы значительно уменьшить объем данных, которые необходимо сохранить, по сравнению с помещением всех значений в базу данных и их индексированием. Предположительно причина использования базы данных в первую очередь заключается в нехватке памяти для полного фильтра Блума.

Другие вопросы по теме