Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
Форум программистов > MySQL > Использование CHAR в качестве PRIMARY |
Автор: fridkaratel 25.11.2012, 08:51 |
Задался вопросом - использование CHAR в качестве ключа PRIMARY... Создал тестовую таблицу на 100 000 строк - разницы на локальном сервере не заметил. То есть, что выборка по INT (11), что выборка по CHAR (12) - дала одинаковые результаты. Хотелось бы узнать, какие есть последствия использования CHAR в качестве ключа? --------------------- Вот пример, где легче работать с CHAR чем с INT. Есть пользователи, есть товары и есть заказанные пользователем товары. Пользователь хочет изменить количество с 10 на 20. При работе с INT необходимо выбрать все товары, заказанные пользователем, чтобы узнать OrderCommodityId в базе. При работе с CHAR нет необходимости выбирать все товары - OrderCommodityId будет всегда UserId + '_' + CommodityId. То есть, при CHAR в качестве PRIMARY KEY не надо делать выборку - а просто одним запросом INSERT ON DUPLICATE KEY UPDATE. --------------------- Посчитаем... Пользователей: 1 000 000 Товаров: 100 000 Получается, что длина макс. OrderCommodityId будет 1000000_100000 - это 15 знаков. --------------------- Выборка по Id будет всегда происходить при условии 100% равенства, т.е. не будет LIKE и т.п. --------------------- Также вижу, что в таком случае нет необходимости удалять значения из БД. Например, пользователь заказал товар. В таблицу добавилась строка с OrderCommodityId=100_999 и количеством. Потом пользователю выдали товар, и количество изменили на 0. В таких случаях, таблица не будет фрагментироваться... --------------------- Если в обработке задействованы, например, 3 таблицы, то опять же надо делать выборку из этих двух таблиц, чтобы получить Id элемента в каждой из них. В случае с CHAR мы через PHP-скрипт генерируем его Id, разделяя нижним слешем, и всё. А потом INSERT ON DUPLICATE KEY UPDATE... --------------------- Что скажете по всему этому? Очень хочется узнать вашего мнения, а также за и против... |
Автор: lomaster 25.11.2012, 09:58 | ||
Вы лучше почитайте про реляционные базы. Тогда лайки, фрагментации и т.п. в голову лезть небудут. |
Автор: fridkaratel 25.11.2012, 12:17 |
Да, но... Например, есть товар: ItemId=123 и Sku=SK91 (Sku - это артикул). Есть несколько складов, где есть этот товар. При выдаче товара я выбираю склад, откуда его выдать. В итоге, мне нет необходимости его искать через SELECT. Достаточно составить ключ из ID склада и ID товара - и всё. А далее через INSERT UPDATE обновить количество на складе. Что выдать 1 товар, что выдать 100 товаров - не надо их выбирать через SELECT WHERE IN (...). Мне вообще не надо знать ID для этого товара на складе. Я его генерирую через PHP и тем же INSERT UPDATE обновляю. Как-то вот так... ![]() Мне кажется, это удобно и... понятней, нежели выбирать ID... Но я сомневаюсь в таком решении, потому как не специалист в области БД, поэтому и попросил советов и рекомендаций... ;-) |
Автор: lomaster 25.11.2012, 14:59 |
Здается мне что у автора склад неправильно сделан, вот и ищет как правильно, но не в той степи. |
Автор: fridkaratel 26.11.2012, 02:41 | ||
@skyboy:
В таблице будет столбец с Id пользователя... И с Id товара... То есть примерно так: - StoreCommId = CHAR (12) - StoreId - CommId - StoreQty Если StoreCommId - это INT (11) с автоувеличением, то в случае обновления более одного товара на складе придётся: А) Или сразу выбрать CommId всех товаров, а потом делать INSERT ON DUPLICATE UPDATE Б) Обновлять без проверки дубликатов, а через WHERE StoreId=A AND CommId=B В случае же использования CHAR в качестве PK отпадёт выборка товаров со склада Мне надо будет в PHP-скрипте сгенерировать StoreCommId из тех значений, которые мне уже известны - StoreId и CommId... Как то так... ;) ------------- @lomaster Здается мне что у автора склад неправильно сделан, вот и ищет как правильно, но не в той степи. Я не являюсь специалистом базах данных, потому не могу точно сказать о правильности своего выбора. Но я стараюсь, учусь ![]() Задал вопрос в поиск, но особо точных ответов никто не дал... Основным минусом CHAR в качестве PK называют то, что при JOIN'ах будет медленней работать, чем при использовании INT. Но мне JOIN'ов и не надо... Мне надо, фактически, обновлять данные запросом INSERT UPDATE без доп. выборки SELECT'ом тех Id, которые затрагиваются. В моём случае, я их могу предугадать со 100% уверенностью... Во-от... |
Автор: skyboy 26.11.2012, 16:49 | ||
я тебе уже писал, что составной уникальный ключ на StoreId + CommId позволяет тебе поступать так же. то есть, SELECT из этой таблицы не происходит? сугубо вставка/обновление? какая странная таблица ![]() |
Автор: lomaster 26.11.2012, 18:17 | ||
|
Автор: fridkaratel 27.11.2012, 06:32 | ||||||
@skyboy:
То есть, получается, если я создам UNIQUE KEY = StoreId + CommId, то мне можно будет точно также делать INSERT ON DUPLICATE KEY UPDATE? Если да, то это здорово! Я просто не знал об этом ![]() Тогда многие вопросы отпадают, в т.ч. и использование CHAR в качестве PRIMARY KEY.
SELECT происходит. Чтобы выдать товар, происходит LEFT JOIN с выборкой кол-ва на складе, чтобы не выдать больше, чем там есть. Но JOIN происходит не по PRIMARY KEY, а по Id склада и артикулу товара. ---------------------------- @lomaster
Чтобы обновить кол-во на складе, зная StoreCommId... Но если можно так, как сказал skyboy, то StoreCommId как-бы и не нужен уже ![]() |
Автор: skyboy 27.11.2012, 08:45 |
меж тем, я уже дважды об этом писал ![]() |
Автор: fridkaratel 27.11.2012, 09:40 | ||||
@skyboy: Большое спасибо за ответы и советы! ;-) Сегодня почитал про ключи и узнал много нового ![]() Есть попутный вопрос (перед закрытием темы)... Чтобы выбрать доступные для резерва товары, я выполняю такой запрос:
Чтобы выбрать долги клиенту, я выполняю такой запрос:
Возникают два вопроса: 1. Не слишком ли они сложные и.. 2. Можно ли их упростить? Комментарий: - У каждого клиента есть менеджер, который его обслуживает, поэтому он учавствует и в резерве товара. - Эти два запроса я подкорректировал для наглядности. То есть, не надо их сопоставлять один с другим. Можно сказать, эти запросы выполняются к двум разным БД с разными структурами таблиц ![]() |
Автор: fridkaratel 29.11.2012, 06:12 |
В качестве эпилога... С запросами разобрался. С использованием CHAR в качестве PRIMARY KEY тоже... Вывод: Не использовать CHAR в качестве PK - использовать составной UNIQUE INDEX по тем столбцам, из которых хотелось сформировать PRIMARY KEY. То есть, если StoreId=3 и CommId=1000, то вместо PRIMARY KEY (AS CHAR) = 3_1000 сделать UNIQUE INDEX на StoreId + CommId. |