SeRu
Зарегистрирован: 23.07.02
Сообщения: 329
|
Добавлено: 25/04/04 в 01:33
|
|
Вот есть у меня база и в ней 8-15 полей, которые могут принимать значения только да или нет, 1 или 0 (истинно или ложно). Например: есть товар в продаже - "1", нету "0". И вот таких полей в SQL базе у меня 8-15штук. Я думаю стоит ли создавать столько полей или можно сделать всё через одно поле? Возможно в этом единственном поле хранить запись типа abcde... cd - есть, а если нету, то abe... Как поступить?
|
K началу
|
|
|
Ru
Зарегистрирован: 17.04.04
Сообщения: 14
|
Добавлено: 25/04/04 в 01:59
|
|
Это зависит от того как у тебя выборка из этой базы идет. Если надо смотреть отдельные товары, то нужно делать разные поля, если все подряд, то лучше в одно поле. И вообще как часто идет постинг. Может каких-то товаров больше, каких-то меньше. Тогда имхо лучше вообще сделать одну таблицу с 2-мя полями (тип товара и наличие его). Ну и можно еще одну таблицу с описанием товара, чтобы самому не запутаться. Хотя наверное последний вариант лучший во всех отношениях
|
K началу
|
|
|
mr.GOD
Зарегистрирован: 19.11.03
Сообщения: 674
|
Добавлено: 25/04/04 в 03:36
|
|
делаешь таблицу:
ид товара(id) | описание товара (desc)| наличие(status)
id - uniq , not null , auto increment desc - text status -char 3 , YES или NO
вот собсно всегда сможешь узнать что и как если я все правильно понял
|
K началу
|
|
|
bleed
Зарегистрирован: 19.02.03
Сообщения: 282
|
Добавлено: 25/04/04 в 05:26
|
|
почитай теорию по базам данных, есть такое понятие как нормализация таблиц, атомарность данных, и т.п. И еще побольше напиши че за поля и че за выборки тебе нужны.
|
K началу
|
|
|
Dragon
Зарегистрирован: 09.02.03
Сообщения: 270
|
Добавлено: 25/04/04 в 08:10
|
|
mr.GOD писал: | desc - text status -char 3 , YES или NO
|
1. Text и Varchar в нагруженной таблице использовать крайне не рекомендуется.
2. "Да" или "Нет" не проще ли хранить как Char(1) в виде единицы или нуля?
|
K началу
|
|
|
SeRu
Зарегистрирован: 23.07.02
Сообщения: 329
|
Добавлено: 25/04/04 в 08:22
|
|
Вот примерно у меня такая ситуация. На странице выводиться список телевизоров 10-200штук, и нужно вывести для каждого телевизора характеристики (эти 8-15 полей): 1) Плоский экран (Да/Нет) 2) Пульт управления (Да/Нет) 3) Телетекст (Да/Нет) 4) Встроенные игры (Да/Нет) ... 15) Пульт управления (Да/Нет)
То есть например. >Philips - [1 .... 15]
>Sony - [1 .... 15]
>Rolsen - [1 .... 15]
|
K началу
|
|
|
Kernel Team
Зарегистрирован: 02.11.03
Сообщения: 147
|
Добавлено: 25/04/04 в 08:51
|
|
SeRu писал: | Возможно в этом единственном поле хранить запись типа abcde... cd - есть, а если нету, то abe... Как поступить? |
Можно создать таблицу с номером товара и описанием товара (в твоем случае характеристики). (номера с 0 до n), а в текстовом поле хранить что-то вроде 1010001001, где порядковый номер будет показателем товара (из первой таблицы), а 1 или 0 - показатель его наличия... К твоему примеру вроде более или менее подходит...
Удачи!
|
K началу
|
|
|
SeRu
Зарегистрирован: 23.07.02
Сообщения: 329
|
Добавлено: 25/04/04 в 08:54
|
|
Вот как раз об этом я и думаю, предложение по одному полю мне пришло как то случайно за пару секунд, когда я писал пост, сомневаюсь, что его реально используют.
|
K началу
|
|
|
Butch
Зарегистрирован: 14.09.03
Сообщения: 92
|
Добавлено: 25/04/04 в 09:41
|
|
Ну если все флаги в твоем случае возможно хранить в одном поле, то я бы предложил хранить их в в целых числах. Работа с числовыми данными всегда быстрее нежели с текстовыми. Смотришь сколько тебе нужно флагов и выбираешь формат целого числа от TINYINT (до 8 флагов) до INT (до 32 флагов). "Назначаешь" соответствие биты-флаги и отсюда пляшешь. Например, 1 бит - наличие на складе, 2 бит - отображать в прайсе, ну и т.д. Соответственно, перед обращением к мускулю формируешь небходимое для запроса число с помощью бинарных операций. НО, такое работает только при строгих запросах. Т.е. если тебе, например, при выборке не важно значение 5,8 и 11-го битов, то тут придутся поплясать, хотя всегда можно найти весьма элегантное решение любой задачи. Главное - это четко знать как все должно работать в итоге ;)))
|
K началу
|
|
|
bleed
Зарегистрирован: 19.02.03
Сообщения: 282
|
Добавлено: 25/04/04 в 10:08
|
|
cjmaster писал: | Можно создать таблицу с номером товара и описанием товара (в твоем случае характеристики). (номера с 0 до n), а в текстовом поле хранить что-то вроде 1010001001, где порядковый номер будет показателем товара (из первой таблицы), а 1 или 0 - показатель его наличия... К твоему примеру вроде более или менее подходит... Удачи! |
как я понял вы хотите всю информацию о продукте хранить в одном поле... мда. Короче, а если ему необходимо будет сделать выборку тех телевизоров у которых плоский экран(например), и что тогда не обойдешся просто SQL запросом к базе, а надо будет обрабатывать каждое полее еще и по символьно... вы сами подумайте какую нагрузку создаст это!!! Я бы сделал так: id unique, not null, auto_increment - primary key name char(15), index - модель desc char(100) - описание rc char(1), index- пульт управления 0 или 1 scr char(1), index- плоский экран game char(1), index- игры ... и т.д. не забудь про индексы
|
K началу
|
|
|
Butch
Зарегистрирован: 14.09.03
Сообщения: 92
|
Добавлено: 25/04/04 в 10:42
|
|
Короче, делаешь числовое поле, где каждый бит отвечает за то или иное свойство. По твоему примеру: 0-ой бит - Плоский экран (Да/Нет) 1-ый - Пульт управления (Да/Нет) 2-ой - Телетекст (Да/Нет) 3-ий - Встроенные игры (Да/Нет) ... 14-й - Virtual Dolby Surround таким образом мы вписываемся в 16 бит, т.е. 2 байта - используем SMALLINT UNSIGNED (беззнаковый, чтоб не особо путаться) Чтобы получить число, которое нужно занести в это поле используем формулу: SETS = N0*2^0 + N1*2^1 + N2*2^2 + N3*2^3 + ... + N14*2^14, где N0-N14 - 0 или 1 (Нет или Да) Для осуществления выборки по определенным пораметрам вычисляем битовую комбинацию, соотвествующую этим параметрам по той же формуле, что и SETS. Например, для поиска ТВ с плоским экраном и VDS это будет RSETS = 2^0 + 2^14. Для строгой выборки (т.е. ТВ имеет только плоский экран и VDS, все остальное отсутствует) используем запрос SELECT * FROM table WHERE SETS=RSETS; Для выборки нестрогих соответствий (где обязательно есть плоский экран и VDS + все что угодно другое) используем запрос вида SELECT *,SETS & RSETS AS FSETS FROM table WHERE FSETS=RSETS; Насчет структуры AS не уверен, посмотри в доках как полю имя присвоить. Или это можно обойти чем-то вроде SELECT SETS & RSETS,* FROM table WHERE 0=RSETS; В общем, это уже детали. Таким образом ты получишь 2 байта на все характеристики вместо 15. Плюс выборка, я думаю, будет пошустрее. По крайней мере я бы сделал так как я описал.
|
K началу
|
|
|
mr.GOD
Зарегистрирован: 19.11.03
Сообщения: 674
|
Добавлено: 25/04/04 в 12:47
|
|
Dragon писал: | 1. Text и Varchar в нагруженной таблице использовать крайне не рекомендуется. 2. "Да" или "Нет" не проще ли хранить как Char(1) в виде единицы или нуля? |
ну во-первых про нагрузки автор топика нечего не сказал ,а во вторых можно и в виде int(1) и еще придумать пару десятков других способов , я просто предложил общую структуру.
з.ы. только сейчас понял что он вообще хотел
|
K началу
|
|
|
undef
Зарегистрирован: 15.09.03
Сообщения: 357
|
Добавлено: 25/04/04 в 13:39
|
|
Можно попробовать использовать битовые маски как в C.
|
K началу
|
|
|
sexvendor
Зарегистрирован: 07.10.03
Сообщения: 66
|
Добавлено: 25/04/04 в 14:12
|
|
Butch писал: | Короче, делаешь числовое поле, где каждый бит отвечает за то или иное свойство. По твоему примеру: 0-ой бит - Плоский экран (Да/Нет) 1-ый - Пульт управления (Да/Нет) 2-ой - Телетекст (Да/Нет) 3-ий - Встроенные игры (Да/Нет) ... 14-й - Virtual Dolby Surround таким образом мы вписываемся в 16 бит, т.е. 2 байта - используем SMALLINT UNSIGNED (беззнаковый, чтоб не особо путаться) Чтобы получить число, которое нужно занести в это поле используем формулу: SETS = N0*2^0 + N1*2^1 + N2*2^2 + N3*2^3 + ... + N14*2^14, где N0-N14 - 0 или 1 (Нет или Да) Для осуществления выборки по определенным пораметрам вычисляем битовую комбинацию, соотвествующую этим параметрам по той же формуле, что и SETS. Например, для поиска ТВ с плоским экраном и VDS это будет RSETS = 2^0 + 2^14. Для строгой выборки (т.е. ТВ имеет только плоский экран и VDS, все остальное отсутствует) используем запрос SELECT * FROM table WHERE SETS=RSETS; Для выборки нестрогих соответствий (где обязательно есть плоский экран и VDS + все что угодно другое) используем запрос вида SELECT *,SETS & RSETS AS FSETS FROM table WHERE FSETS=RSETS; Насчет структуры AS не уверен, посмотри в доках как полю имя присвоить. Или это можно обойти чем-то вроде SELECT SETS & RSETS,* FROM table WHERE 0=RSETS; В общем, это уже детали. Таким образом ты получишь 2 байта на все характеристики вместо 15. Плюс выборка, я думаю, будет пошустрее. По крайней мере я бы сделал так как я описал. |
Butch, откуда такое стремление сэкономить несколько байт на запись, в колосальный ущерб производительности. Хотел написать полный ответ, но bleed пару постами выше уже практически всё сказал. Т.е. представь, у тебя есть телевизоры с д/у и без него. Сделав соотв. выборку по таблице и имея индекс по этому полю, ты быстро получишь tv с д/у или без. В противном же случае ты заставишь бд считать ВСЕ (это ключевое слово) записи, произвести с ними битовые операции, и выдать тебе отфильтрованный результат. Имея таблицу в 100 записей это особо не почувствуешь разницу, но при увеличении объёма хранимой информации, производительность будет резко падать.
|
K началу
|
|
|
SeRu
Зарегистрирован: 23.07.02
Сообщения: 329
|
Добавлено: 25/04/04 в 14:28
|
|
То есть всё-таки советуете создавать дополнительно 8-15 полей в базе?
|
K началу
|
|
|
Jark
Зарегистрирован: 05.01.04
Сообщения: 92
|
Добавлено: 25/04/04 в 15:54
|
|
тебе оптимизация для чего нужна? для скорости или простоты работы? вряд ли ты делаешь CJ под TV трафик ;)
|
K началу
|
|
|
Ru
Зарегистрирован: 17.04.04
Сообщения: 14
|
Добавлено: 25/04/04 в 16:06
|
|
Это будет нихрена не универсальный вариант. Если например добавится еще 10 характеристик, придется базу менять. А это не есть гуд. Я бы сделал так
1-я таблица table tv id int NOT NULL AUTO_INCREMENT PRIMARY KEY, desc varchar(255) можно добавить еще полей, которые будут относиться только к этому телеку, например картинку или еще что
2-я таблица table feature id int NOT NULL AUTO_INCREMENT PRIMARY KEY, desc varchar(255) можно также здесь добавить поля, например история появления этой возможности в телевизорах
3-я таблица - связка между двумя предыдущими table tv2feature id int NOT NULL AUTO_INCREMENT PRIMARY KEY, tv_id int NOT NULL, feature_id NOT NULL, UNIQUE (tv_id,feature_id), INDEX tv (tv_id)
тогда получается неограниченное количество описаний товара (features) для показа информации по нужному телевизору делаешь select tv.desc as 'tv_desc', feature.desc as 'feature_desc' from tv left join tv2feature on tv2feature.tv_id=tv.id left join feature on feature.id=tv2feature.feature_id where tv.id='ид нужного тебе телека'
вот, что скажешь?
|
K началу
|
|
|
SeRu
Зарегистрирован: 23.07.02
Сообщения: 329
|
Добавлено: 25/04/04 в 16:56
|
|
Скорость работы имеет первостепенное значение! поэтому не знаю имеет ли смысл разбивать таблицу на несколько таблиц. Безусловно могут появиться новые характеристики, тогда действительно придётся менять базу, вот и ищу приемлемый вариант.
|
K началу
|
|
|
sexvendor
Зарегистрирован: 07.10.03
Сообщения: 66
|
Добавлено: 25/04/04 в 17:05
|
|
Ru писал: | Это будет нихрена не универсальный вариант. Если например добавится еще 10 характеристик, придется базу менять. А это не есть гуд. Я бы сделал так 1-я таблица table tv id int NOT NULL AUTO_INCREMENT PRIMARY KEY, desc varchar(255) можно добавить еще полей, которые будут относиться только к этому телеку, например картинку или еще что 2-я таблица table feature id int NOT NULL AUTO_INCREMENT PRIMARY KEY, desc varchar(255) можно также здесь добавить поля, например история появления этой возможности в телевизорах 3-я таблица - связка между двумя предыдущими table tv2feature id int NOT NULL AUTO_INCREMENT PRIMARY KEY, tv_id int NOT NULL, feature_id NOT NULL, UNIQUE (tv_id,feature_id), INDEX tv (tv_id) тогда получается неограниченное количество описаний товара (features) для показа информации по нужному телевизору делаешь select tv.desc as 'tv_desc', feature.desc as 'feature_desc' from tv left join tv2feature on tv2feature.tv_id=tv.id left join feature on feature.id=tv2feature.feature_id where tv.id='ид нужного тебе телека' вот, что скажешь? |
Хороший вариант, только не много не правильно третья таблица сделана. Лучше так:
tv_id int unsigned NOT NULL, feature_id int unsigned NOT NULL, PRIMARY KEY (tv_id,feature_id)
Так же сделать тип этих трёх таблиц InnoDB (на сколько можно предположить что речь идёт о MySQL) и создать внешние ключи.
|
K началу
|
|
|
Butch
Зарегистрирован: 14.09.03
Сообщения: 92
|
Добавлено: 25/04/04 в 19:52
|
|
sexvendor писал: | Butch, откуда такое стремление сэкономить несколько байт на запись, в колосальный ущерб производительности. Хотел написать полный ответ, но bleed пару постами выше уже практически всё сказал. Т.е. представь, у тебя есть телевизоры с д/у и без него. Сделав соотв. выборку по таблице и имея индекс по этому полю, ты быстро получишь tv с д/у или без. В противном же случае ты заставишь бд считать ВСЕ (это ключевое слово) записи, произвести с ними битовые операции, и выдать тебе отфильтрованный результат. Имея таблицу в 100 записей это особо не почувствуешь разницу, но при увеличении объёма хранимой информации, производительность будет резко падать. |
Не буду спорить, т.к. все зависит от конкретной задачи - где-то выгоднее использовать одно число как массив флагов и бинарные операции, где-то раздельные значения по каждому параметру. По данной задаче вообще не понимаю актуальности вопроса - хорошо если моделей телевизоров наберется под пару тысяч, так что можно делать как угодно. И лучше делать какой-нибудь универсальный вариант, чтобы потом можно было элементарно редактировать наборы параметров.
|
K началу
|
|
|
SeRu
Зарегистрирован: 23.07.02
Сообщения: 329
|
Добавлено: 25/04/04 в 21:08
|
|
Для меня очень актуально. Как я понял из дискуссии есть 3 метода. 1) База с полями 2) База с 1 универсальным полем 3) Разбить базу на различные таблицы
|
K началу
|
|
|