2012-02-06 2 views
2

Мне нужно хранить в таблице MySQL длинные битовые строки, которые могут быть длиной до 32768 бит. Необходимость этих данных не требуется индексировать или искать в полном объеме в любое время. Если я правильно прочитал, этот размер должен быть хорошо как в моем max_packet_size, так и в пределе размера строки @ 65k.Каков наиболее эффективный тип данных MySQL для длинных битовых строк?

В идеале я хотел бы хранить строки (и ВСТАВИТЬ их) в формате 0b, но это не является обязательным требованием ... все, что даст мне существенно 1: 1 данные на диске, было бы здорово.

BLOB-файлы, похоже, недостаточно хорошо выполняются, поскольку строка, состоящая только из единиц и нулей ('010101010101'), не отличается от обычного текста и стоит мне L байтов + 2. BIT() будет идеально , но ограничивается только максимальной длиной 64 бит.

Хотя значительная часть данных (90% +) была бы достаточно представлена ​​в неподписанном Bigint, оставшиеся 10% строк заставляют меня находить более элегантное решение, чем разделение их логически (т. Е. Поиск вторичной таблицы if не найден в первой, вторичной таблице с использованием BLOB для оставшихся 10% строк и т. д.).

Дополнительный бонус будет любого типа, который разрешает побитовые операции, но если нет, это также легко сделать за пределами сервера MySQL.

Каков наиболее эффективный тип данных для этой цели?

ответ

2

Я бы сказал, что это зависит от вашего шаблона доступа. Если вы можете позволить себе читать/записывать всю битовую строку при каждом доступе, то varbinary (4096) будет работать нормально и быть довольно компактным (всего 2 байта служебных данных для всего поля). В этой модели один бит на стороне приложения действительно представлен одним битом в хранилище данных, и клиентское приложение может интерпретировать его как битовую строку (выполнение побитовых операций и т. Д.)

Если вы хотите оптимизировать немного больше, вы можете представить себе таблицу с BIGINT и VARBINARY (4096):

create table dummy (
    dummykey int not null, 
    bit1 bigint null, 
    bit2 varbinary(4096) null, 
    primary key(dummykey) 
); 

только один из двух полей не является нулевым для данной записи. Если бит1 не является нулевым, то он может хранить 64 бита. Для больших битовых строк бит1 имеет значение null, а вместо него используется бит2. Клиентское приложение должно быть достаточно умным, чтобы обрабатывать все побитовые операции (уделяя особое внимание подписанным/неподписанным вопросам с бит1).

+0

Я также изучал varbinary, но в соответствии с [требованиями к хранилищу] (http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html) не varbinary (32768) все равно стоил мне 1 байт за бит моей битовой строки ...или я должен ожидать, что это так же оптимизировано, как это может быть для строк, которые долго? – hexparrot

+0

Nevermind, я понимаю ваше предложение: каждый бит в varbinary (4096) вместо этого будет символом, который бит-бит-бит представляет 8 символов моей строки, и я просто перебираю строку varbinary для определения этих значений и восстановления окончательной строки бита , Это определенно идеально, так как я более чем готов торговать вычислительным временем на клиенте для хранения и времени доступа на сервере. Спасибо! – hexparrot

1

Я думаю, что тип BLOB - это то, что вам нужно. Он может представлять двоичные строки до 2^16 байт и имеет накладные расходы на 2 байт в записи (если L является длиной в байт значения, L + 2 байт является его размер на диске) ,

Затем, если вы действительно хотите оптимизировать, использовать две таблицы, одна с BLOB, а другой с TINYBLOB (строки до 2^8 байт, 1 байт накладные расходы), а затем UNION их вместе в ЗРЕНИЯ или во время SELECT.

Если вы хотите оптимизировать еще больше, использовать третью таблицу с BIGINT (это позволит хранить двоичные строки длиной до 58 бит , так как остальные 6 будут необходимы для хранения длины двоичной строки).

+0

Одна из основных причин, по которым я был так доволен ответом от @Didier, заключается в том, что это касалось моей основной заботы о минимальном использовании дискового хранилища. Использование BLOB или TINYBLOB для хранения двоичных строк по-прежнему стоит 1 байт на бит, например, «01010101» стоит 8 байтов (8 бит на символ) под этими типами. Две или три таблицы, объединенные против нуля BIGINT, нулевой VARBINARY, похоже, что он отклоняется от принципа KISS, но спасибо за ваш вклад. – hexparrot

+0

@hexparrot вы можете указать в руководстве, где говорится, что вы утверждаете? AFAIU, руководство по MySQL говорит, что для хранения 1 байта в TINYBLOB потребуется 2 байта на диске, а не 8. – CAFxX

+0

[Требования к хранилищу] (http://dev.mysql.com/doc/refman/5.0/en/storage-requirements .html) показывают, что blob принимает «L + 2 байта, где L <2^16», где «L представляет фактическую длину в байтах заданного строкового значения». Поскольку ваше решение не рекомендует одинаковое поразрядное разборку принятого решения, я могу предположить, что вы имеете в виду для моей строки «10101010», которая должна быть сохранена AS-IS, которая будет иметь 8 символов по 1 байт каждый. Помните, что это строго касается хранения фактических данных, а не явных накладных расходов, которые действительно равны 2 байтам на BLOB. – hexparrot