2009-02-05 3 views
10

Мне нужно создать таблицу Key/value в моей базе данных, и я ищу руководство для наилучшего способа сделать это. В принципе, мне нужно уметь сопоставлять значения с динамическим набором именованных свойств и применять их к внешнему ключу.Пара ключей/значений в таблице базы данных

Операции, мне нужно, чтобы быть в состоянии поддерживать являются:

  • Применить пару ключ/значение для группы элементов
  • Перечислите все в настоящее время активных ключей
  • определить все элементы, которые имеют значение для заданного ключа
  • Определите все элементы, в которых значение, связанное с данным ключом, соответствует некоторым критериям.

Кажется, что самый простой способ сделать это, чтобы определить таблицу:

CREATE TABLE KeyValue (
    id int, 
    Key varchar..., 
    Value varchar... 
); 

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

Каков наилучший способ для этого?

ответ

1

Опцией, которую стоит изучить, является переваривание ключа с использованием SHA1 или MD5 перед его вставкой в ​​таблицу.

Это позволит вам избавиться от таблицы поиска, но вы не сможете перебирать ключи, потому что это происходит только в одном направлении.

1

Мне кажется, что у вас может быть пара вариантов дизайна.

Выбор 1: Дизайн две таблицы вы намекаете в своем ответе

Keys (
id int not null auto_increment 
key string/int 
) 
values (
id int not null auto_increment 
key_id int 
value string/varchar/int 
) 

Выбор 2: возможно, sambo99 отметил, вы могли бы изменить это:

keys (
id int not null auto_increment 
key string/int 
hash_code int -- this would be computed by the inserting code, so that lookups would effectively have the id, and you can look them up directly 
) 

values (
id int not null auto_increment -- this column might be nice since your hash_codes might colide, and this will make deletes/updates easier 
key_id int -- this column becomes optional 
hash_code int 
value string/varchar/int... 
) 

-

+0

Шансы столкновения SHA1 в значительной степени 0 в действительности, вам нужно быть супер злым, чтобы вызвать столкновения, если вы очень обеспокоены тем, что можете использовать SHA256 –

+2

Я лично видел столкновение хэша (TTH) в DC++, так что это не возможно. – erikkallen

5

Не оптимизируйте это, если вам не нужно. Какова средняя длина ключа? Будет ли эта таблица такой большой, что она не будет вписываться в память вашего сервера, если вы реализуете ее наивным образом? Я бы предложил реализовать его самым простым способом, измерить производительность, а затем повторно реализовать, только если производительность является проблемой.

Если производительность является проблемой, то использование целочисленного ключа и отдельной таблицы, вероятно, является способом перехода (JOINS на целочисленных столбцах обычно быстрее, чем JOINS с использованием столбцов с переменной длиной строки). Но первое правило оптимизации - MEASURE FIRST - убедитесь, что ваш предположительно оптимизированный код действительно ускоряет работу.

+1

+1 простота. Если влияние производительности не будет очевидным и серьезным, всегда используйте то, с чем проще всего работать, а затем проверяйте и оптимизируйте по мере необходимости. –

30

Вы используете модель базы данных по имени Entity-Attribute-Value.Это общий способ хранения пар ключ/значение в реляционной базе данных, но он имеет ряд недостатков в отношении нормализации и эффективности базы данных.

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

Применить пару ключ/значение к группе элементов: Вам нужно добавить одну строку для каждого элемента в группе.

INSERT INTO KeyValue (id, key, value) VALUES (101, 'color', 'green'); 
INSERT INTO KeyValue (id, key, value) VALUES (102, 'color', 'green'); 
INSERT INTO KeyValue (id, key, value) VALUES (103, 'color', 'green'); 

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

Перечислите все в настоящее время активных ключей:

SELECT DISTINCT Key FROM KeyValue; 

Определить все элементы, которые имеют значение для данного ключа:

SELECT id FROM KeyValue WHERE Key = 'color'; 

определить все где значение, связанное с данным ключом, соответствует некоторым критериям:

SELECT id FROM KeyValue WHERE Value = 'green'; 

Некоторые из проблем, связанных с Entity-Attribute-Value являются:

  • Ни в коем случае, чтобы убедиться, что ключи пишутся одинаково для всех элементов
  • Ни в коем случае, чтобы сделать некоторые ключи обязательными для всех элементов (т.е. NOT NULL в обычном дизайне стола).
  • Все ключи должны использовать VARCHAR для значения; не может хранить разные типы данных для каждого ключа.
  • Невозможно использовать ссылочную целостность; не может сделать FOREIGN KEY, который применяется к значениям некоторых ключей, а не другим.

В принципе, значение атрибута-объекта не является нормализованным дизайном базы данных.

Смежные вопросы