Есть объекты, классифицированные по категориям. В каждой категории объекты имеют собственный набор свойств. Сейчас решил делать следующим образом: [sql]CREATE TABLE `objects` ( `obj_id` int(11) NOT NULL auto_increment, `obj_name` varchar(255) NOT NULL, /* имя объекта */ `cat_id` int(11) NOT NULL /* категория в которой он располагается */ PRIMARY KEY (`war_id`) ) ENGINE=MyISAM; CREATE TABLE `objects_props` ( /* имена свойств вынес в отдельную таблицу потому как предпологается около 500000 обектов и у каждого в среднем 10 свойств. предпологаю что так будет быстрее */ `obj_property_id` int(11) NOT NULL auto_increment, `cat_id` int(11) default NULL, /* категория для которой создано свойство (необходимо для заполнения БД) */ `obj_property_name` varchar(100) NULL, /* Имя свойства */ `wpr_basic` enum('true','false') 'true', /* Является ли свойство "обязательным" */ PRIMARY KEY (`wpr_id`) ) ENGINE=MyISAM; CREATE TABLE `objects_props_vals` ( `obj_id` int(11) NOT NULL, /* объект к которому относится значение */ `obj_property_id` int(11) default NULL, /* через это поле получаю имя свойства */ `obj_property_value` varchar(255) NULL /* Значение свойства */ ) ENGINE=MyISAM; CREATE TABLE `objects_images` ( `img_id` int(11) NOT NULL auto_increment, /* по нему определяю приоритет отображения изображений (чем меньше id тем выше приоритет) */ `obj_id` int(11) NOT NULL, /* объект к которому привязано изображение */ `img_name` varchar(255) NOT NULL, /* имя файла с изображением */ PRIMARY KEY (`img_id`) ) ENGINE=MyISAM;[/sql] Нужно реализовать "постраничный" вывод объектов и свойств. Сейчас выбираю obj_id по cat_id и в цикле делаю запросы для каждого obj_id. Только вот не нравиться мне такой метод и всем телом чувствую что так не правильно. Помогите составить запрос, который вытащил бы допустим с 10 по 25 объекты и все их свойства и картинку с наибольшим приоритетом. А еще лучше если я в корне не правильно "спроектировал" структуру базы данных и найдется добрая душа которая объяснит как лучше
структура нормальная. если речь идет о листалке, то скорости хватит, лучше будет написать фюнкцию getObjProps($obj), которая уже выдает данные по объекту. Это если надо шлепать тысячи или больше записей, то стоит заморачиваться так PHP: select * from objects_props op, obj_vals ov where op.pid=ov.pid and ov.obj_id in (select obj_id from obj where cat_id='".$cat_id."' limit 10,25) привязывать свойства к конкретным объектам обязательно? obj_id в props?
у меня сейчас так и есть только вот получается что если на страницу 15 записей как в примере то получиться минимум 16 запросов + из других мест. а если ещё и нужно будет вывести не 15 а допустим 40 объектов. помоему ~40 запросов на страницу это критично. Или это мое заблуждение о том что некультурно пихать запросы в цикл и вобще чем меньше запросов на страницу тем лучше? Вот тут не понял. `objects_props` нет obj_id. cat_id необходим для добавления новых объектов, что бы выводить форму ввода значений свойств. `objects_props_vals` а тут obj_id связывает конкретное значение свойства с объектом. без него никак. Но все равно спасибо! С удовольствием выслушал бы чье либо ещё мнение по этому поводу.
если у тебя не 100к+ записей - то важнее читаемость кода, скорость отладки и внесения изменений. угу, не углядел.
[sql]CREATE TABLE `objects_props` ( /* имена свойств вынес в отдельную таблицу потому как предпологается около 500000 обектов и у каждого в среднем 10 свойств. предпологаю что так будет быстрее */[/sql] 500k записей и для каждого объекта нужно с этой табличкой работать именно поэтому я и парюсь. тестировал на Amd64 3500+ 1,5 Гб ОЗУ mysql Ver 14.12 Distrib 5.0.22, for pc-linux-gnu (i486) using readline 5.1 и на этом медленно получается страница по несколько секунд генирируется если не кешированная и на ней объектов 30
все равно странно. Индексы все нужные расставил? если не поможет то [sql]select * from objects_props op, obj_vals ov where op.pid=ov.pid and ov.obj_id in (select obj_id from obj where cat_id='".$cat_id."' limit 10,25) order by ov.obj_id[/sql] и одним циклом по ним проходить. Но надо искать в чем причина, даже 40 таких мелких запросов не должны сильно тормозить, а уж на выделеном сервере явно причина где-то еще.
именно так и правильно. на 1000000 объектов такой будет затык... мама-не-горюй... я пошел дальше и в таблице objects храню кеш как serialize($object). тогда выборка идет сразу.
во-первых вы реально намудрили с индексами. поправьте primary key для objects и objects_props. создайте там же индексы на cat_id. в objects_props_vals первичным ключом будет, как я отсюда вижу, (obj_id, obj_property_id). далее на странице у вас должен быть один запрос. кстати, вот он: [sql]select * from objects join objects_props_vals using(obj_id) join objects_props using(obj_property_id) order by obj_name, obj_property_name limit x,x*page_no[/sql] здесь x = количество свойств объекта в данной категории * количество объектов на странице. в цикле проверяете, не изменился ли obj_id в строке. если изменился, значит можете выводить таблицу с предыдущим obj_id и его свойствами из буфера и обнулять буфер. затем добавляете очередное свойство в буфер для текущего obj_id. не забудьте, что после окончания цикла буфер будет заполнен свойствами последнего объекта, который надо вывести.
у одного объекта может быть не одна картинка. то есть на объект с ИД 35 могут быть картинки с ИД 2,54,7623,9999 иногда нужно только с наименьшим ИД а иногда все. проще отдельным запросом выбирать картинки?
при постраничном выводе нескольких объектов на странице у вас отображается только одна картинка на объект?
При постраничном да. То есть вы предлогаете хранить имя картинки с наибольшим приоритетом и не выбирать её из таблицы с картинками?