За последние 24 часа нас посетили 17650 программистов и 1284 робота. Сейчас ищут 1446 программистов ...

Помогите с запросом а может и с самой структурой

Тема в разделе "MySQL", создана пользователем Lacki, 22 май 2007.

  1. Lacki

    Lacki Активный пользователь

    С нами с:
    25 июл 2006
    Сообщения:
    18
    Симпатии:
    0
    Есть объекты, классифицированные по категориям. В каждой категории объекты имеют собственный набор свойств.
    Сейчас решил делать следующим образом:

    [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 объекты и все их свойства и картинку с наибольшим приоритетом.
    А еще лучше если я в корне не правильно "спроектировал" структуру базы данных и найдется добрая душа которая объяснит как лучше :)
     
  2. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    структура нормальная.
    если речь идет о листалке, то скорости хватит, лучше будет написать фюнкцию getObjProps($obj), которая уже выдает данные по объекту.
    Это если надо шлепать тысячи или больше записей, то стоит заморачиваться так
    PHP:
    1.  
    2. 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?
     
  3. Lacki

    Lacki Активный пользователь

    С нами с:
    25 июл 2006
    Сообщения:
    18
    Симпатии:
    0
    у меня сейчас так и есть только вот получается что если на страницу 15 записей как в примере то получиться минимум 16 запросов + из других мест. а если ещё и нужно будет вывести не 15 а допустим 40 объектов. помоему ~40 запросов на страницу это критично. Или это мое заблуждение о том что некультурно пихать запросы в цикл и вобще чем меньше запросов на страницу тем лучше?

    Вот тут не понял.
    `objects_props` нет obj_id. cat_id необходим для добавления новых объектов, что бы выводить форму ввода значений свойств.
    `objects_props_vals` а тут obj_id связывает конкретное значение свойства с объектом. без него никак.

    Но все равно спасибо! С удовольствием выслушал бы чье либо ещё мнение по этому поводу. :)
     
  4. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    если у тебя не 100к+ записей - то важнее читаемость кода, скорость отладки и внесения изменений.
    угу, не углядел.
     
  5. Lacki

    Lacki Активный пользователь

    С нами с:
    25 июл 2006
    Сообщения:
    18
    Симпатии:
    0
    [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 :(
     
  6. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    все равно странно. Индексы все нужные расставил?
    если не поможет то
    [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 таких мелких запросов не должны сильно тормозить, а уж на выделеном сервере явно причина где-то еще.
     
  7. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    именно так и правильно. на 1000000 объектов такой будет затык... мама-не-горюй...

    я пошел дальше и в таблице objects храню кеш как serialize($object). тогда выборка идет сразу.
     
  8. Lacki

    Lacki Активный пользователь

    С нами с:
    25 июл 2006
    Сообщения:
    18
    Симпатии:
    0
    Спасибо за советы
     
  9. stas_t

    stas_t Активный пользователь

    С нами с:
    24 апр 2007
    Сообщения:
    500
    Симпатии:
    0
    Адрес:
    Courbevoie, France
    во-первых вы реально намудрили с индексами. поправьте 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.

    не забудьте, что после окончания цикла буфер будет заполнен свойствами последнего объекта, который надо вывести.
     
  10. stas_t

    stas_t Активный пользователь

    С нами с:
    24 апр 2007
    Сообщения:
    500
    Симпатии:
    0
    Адрес:
    Courbevoie, France
    да, насчёт картинки. её id должен быть в objects. тогда подключить можно будет в том же запросе.
     
  11. Lacki

    Lacki Активный пользователь

    С нами с:
    25 июл 2006
    Сообщения:
    18
    Симпатии:
    0
    у одного объекта может быть не одна картинка. то есть на объект с ИД 35 могут быть картинки с ИД 2,54,7623,9999
    иногда нужно только с наименьшим ИД а иногда все.
    проще отдельным запросом выбирать картинки?
     
  12. stas_t

    stas_t Активный пользователь

    С нами с:
    24 апр 2007
    Сообщения:
    500
    Симпатии:
    0
    Адрес:
    Courbevoie, France
    при постраничном выводе нескольких объектов на странице у вас отображается только одна картинка на объект?
     
  13. Lacki

    Lacki Активный пользователь

    С нами с:
    25 июл 2006
    Сообщения:
    18
    Симпатии:
    0
    При постраничном да. То есть вы предлогаете хранить имя картинки с наибольшим приоритетом и не выбирать её из таблицы с картинками?
     
  14. stas_t

    stas_t Активный пользователь

    С нами с:
    24 апр 2007
    Сообщения:
    500
    Симпатии:
    0
    Адрес:
    Courbevoie, France
    img_id в objects