Я столкнулся с проблемой при разработке схемы таблиц для нашей системы.
Вот ситуация:
В нашей системе много элементов (более 20 миллионов), каждый элемент имеет уникальный идентификатор, но для каждого элемента может быть много записей. Например, для элемента с идентификатором 1 существует около 5000 записей, и каждая запись имеет более 20 атрибутов. Необходимо идентифицировать его идентификатор и статус одного или нескольких его атрибутов для использования в select
, update
или delete
.
Я хочу использовать innodb
Но проблема в том, что при использовании innodb должен быть индекс кластера.
Из-за описанной выше ситуации, похоже, нужно было найти индекс кластера, поэтому я могу использовать только auto_increment int
в качестве ключа
Текущая конструкция выглядит следующим образом:
create table record (
item_key int(10) unsigned NOT NULL AUTO_INCREMENT,
item_id int(10) unsigned NOT NULL,
attribute_1 char(32) NOT NULL,
attribute_2 int(10) unsigned NOT NULL,
.
.
.
.
.
attribute_20 int(10) unsigned NOT NULL,
PRIMARY KEY (`item_key`),
KEY `iattribute_1` (`item_id`,`attribute_1`),
KEY `iattribute_2` (`item_id`,`attribute_2`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=latin1
инструкция sql:
select * from records
where item_id=1 and attribute_1='a1' and attribute_2 between 10 and 1000;
Операторы update
и delete
похожи.
Я не думаю, что это хороший дизайн, но я не могу думать ни о чем другом; все предложения приветствуются.
Извините, если я не задал вопрос.
То, что я хочу получить (выбрать, обновить, удалить, вставить), это записи, а не элементы. Элементы имеют собственные атрибуты, но в приведенных выше описаниях атрибуты, о которых я упоминал, относятся к записям.
Каждый элемент может иметь много записей, например, элемент 1 имеет около 5000 записей.
Каждая запись имеет 42 атрибута, некоторые из них могут быть NULL, каждая запись имеет уникальный идентификатор, этот идентификатор уникален среди разных элементов, но этот идентификатор является строкой, а не числом
Я хочу получить доступ к записям следующим образом:
а. Я буду получать (или обновлять или удалять) записи, относящиеся к одному конкретному элементу, вовремя или в одном запросе
В. Я получаю или обновляю значения всех атрибутов или некоторых конкретных атрибутов в запросе
С. Атрибуты, которые в состоянии запроса могут не совпадать с атрибутами, которые я хочу.
Таким образом, могут быть некоторые операторы SQL, например:
Select attribute_1, attribute_N from record_table_1 where item_id=1 and attribute_K='some value' and attribute_M between 10 and 100
И причины, по которым я думаю, что оригинальный дизайн не очень хорош:
Я не могу выбрать атрибут или идентификатор записи в качестве первичного ключа, потому что это бесполезно, в каждом запросе я должен назначить идентификатор элемента и некоторые атрибуты в качестве условия запроса (например, "where" item_id = 1 и attribute_1 = 'value1' и attribte_2 между 2 и 3), поэтому я могу использовать только номер auto_increment int в качестве первичного ключа. Результатом этого является то, что каждый запрос должен сканировать два b-дерева, и он выглядит например, сканирование вторичного индекса неэффективно.
Также составные клавиши кажутся бесполезными, поскольку условие запроса может варьироваться между многими атрибутами.
С оригинальным дизайном кажется, что я добавляю много индексов для удовлетворения различных запросов, в противном случае мне приходится иметь дело с полной проблемой сканирования таблицы, но очевидно, что слишком много индексов не подходит для обновлять, удалять, вставлять операции.
Если вам нужен индекс кластера и вы не хотите использовать механизм myisam, похоже, что вы должны использовать две таблицы: одну для уникальных свойств элементов, а другую для каждого экземпляра элемента (с указанным атрибуты).
Вы правы, схема неправильная. Наличие атрибута 1..20 в качестве полей в таблице не является способом сделать это, вам нужна отдельная таблица для хранения этой информации. Эта таблица будет иметь item_key
из этой записи вместе со своими собственными key
и value
, и поэтому эта вторая таблица будет иметь индексы, которые позволяют значительно лучше искать.
Что-то вроде следующего:
Глядя на диаграмму, очевидно, что что-то не так, потому что таблица record
слишком пуста, это выглядит не так, как мне кажется, мне что-то не хватает в исходном вопросе....
Я думаю, может быть, вы ищете сложный ключ, а не кластерный индекс, который другой. Вы можете достичь этого путем:
create table record (
item_id int(10) unsigned NOT NULL,
attribute_1 char(32) NOT NULL,
attribute_2 int(10) unsigned NOT NULL,
.
.
.
.
.
attribute_20 int(10) unsigned NOT NULL,
PRIMARY KEY (`item_id`,`attribute_1`,`attribute_2`),
KEY `iattribute_1` (`item_id`,`attribute_1`),
KEY `iattribute_2` (`item_id`,`attribute_2`)
) ENGINE=InnoDB AUTO_INCREMENT=22 DEFAULT CHARSET=latin1