За последние 24 часа нас посетили 19607 программистов и 1605 роботов. Сейчас ищут 860 программистов ...

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

Тема в разделе "MySQL", создана пользователем inline, 14 фев 2011.

  1. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    Есть table1
    id name
    1 name_1
    2 name_2
    ..............
    n name_n

    Есть table2
    1 name_1
    2 name_2
    ..............
    n name_n

    делаю запрос select table1.id,table2.id from table1,table2 where LOCATE(table1.name,table2.name)>0

    как ускорить?
    нужно имено через LOCATE
     
  2. Gromo

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

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    обычно ускорение достигается за счёт правильной индексации полей
     
  3. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    наличие индексов на поля name не ускорило процес
     
  4. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    как будет правильно в даном ситуации?
     
  5. Gromo

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

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    inline
    дело в том, что функция locate (от которой по условию нельзя избавляться) каждый раз парсит строки одной таблицы в поисках подстроки другой. потому-то индексация и не очень сильно помогает. есть команда explain, который используется для отслеживания схемы запроса. но это тоже не самое хорошее решение.
    самое хорошее - переделать структуру базы под данное условие. либо же пользоваться кешированием запросов.
     
  6. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    что ты имееш ввиду под переделать структуру базы под данное условие?
     
  7. Gromo

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

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    inline
    добавление дополнительного поля/полей, которые можно использоваться с индексами для ускорения запроса.
    конкретное решение зависит от конкретной реализации, т.е. универсального решения нет.
     
  8. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    В моем случаи так
    Есть таблица названий моделей и таблица прайсов
    Нужно для каждой модели определить записи из прайсов

    Вот например
    в таблице моделей есть модель Nokia X6
    в таблице прайсов Nokia X6 red, Nokia X6 green
     
  9. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    как быть в таком случаи?
     
  10. Gromo

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

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    если запрос на выборку производится часто, а прайсы обновляются редко, то в таблицу прайсов необходимо добавить айди из таблицы моделей.

    Структура таблиц:
    [sql]CREATE TALBE prices (
    `price_id` INT NOT NULL AUTO_INCREMENT,
    `model_id` INT DEFAULT NULL,
    `name` VARCHAR(200),
    `price` INT DEFAULT NULL,

    PRIMARY KEY(`price_id`)
    );

    INSERT INTO prices VALUES (NULL, NULL, 'Nokia X6 green', 100), (NULL, NULL, 'Nokia X6 red', 120);

    CREATE TALBE models (
    `model_id` INT NOT NULL AUTO_INCREMENT,
    `name` VARCHAR(200),

    PRIMARY KEY(`model_id`)
    );

    INSERT INTO models VALUES (NULL, 'Nokia X6');[/sql]


    Медленный запрос на заполнение айди моделей в таблице прайсов (после добавления/обновления прайсов):

    [sql]UPDATE prices SET model_id = (SELECT model_id FROM models WHERE LOCATE(models.`name`, prices.`name`)>0 LIMIT 1);[/sql]

    Быстрый запрос на выборку:
    [sql]SELECT price_id, price, model_id FROM prices LEFT JOIN models USING(model_id);[/sql]
     
  11. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    Gromo
    в том и дело, что в таблице прайсов model_id так как для каждой строчки прайса его нужно определить
     
  12. Gromo

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

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    inline
    чего ты ждёшь от запроса? списка соответствий айди прайсов и моделей, так? я вроде это и дал. чем плохо предложенное решение?

    как часто обновляется таблица прайсов? если чаще 2 раз в час, то обновляй значение model_id для таблицы прайсов сразу при вставке с помощью триггеров.
     
  13. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    списка соответствий айди прайсов и айди моделей
    одни прайсы раз в два часа, другие раз в сутки

    Gromo
    ты хочеш сказать что
    =
    грубо говоря - два разных способа сделать одно и тоже ?


    [/quote]
     
  14. Gromo

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

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    inline
    твой запрос каждый раз проверяет соответствия строк, мой же способ позволяет делаеть это всего один раз - сразу после обновления прайсов. запросы на айди будут выполняться со сверхсветовой скоростью.

    нет, не одно и то же. первый запрос подготоваливает таблицу для второго запроса.
    если нужны только айдишки, то второй запрос даже проще SELECT price_id, model_id FROM prices.
     
  15. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    Gromo
    опишу ситуацию еще раз
    что есть
    есть таблица прайсов, в ней id,name,price
    есть таблица моделей, в ней id,name

    что нужно
    Нужно ускорить или заменить запрос [sql]select models.id,prices.id from model,prices where LOCATE(model.name,prices.name)>0[/sql]

    На примере
    models
    1 Nokia X6
    2 LG KP500

    prices
    1 Nokia X6 green
    2 Nokia X6 red
    3 LG KP500 yelow
    4 LG KP500 black
    5 LG KP500 red
    6 Ipad 4g

    Результат
    1 1
    1 2
    2 3
    2 4
    2 5
     
  16. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    имено этот запрос все и тормозит
    в таблице models 75k записей, а в prices почти 300k
     
  17. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    это всего, а каждый раз новых строк в прайсах около 3к
    но даже в 3к пересмотреть соответствие для 75к моделей по времени и ресурсах напряжно
     
  18. Gromo

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

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    inline
    блин, нет слов
     
  19. inline

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

    С нами с:
    21 май 2010
    Сообщения:
    466
    Симпатии:
    0
    Gromo
    ты хочеш сказать, что UPDATE prices SET model_id = (SELECT model_id FROM models WHERE LOCATE(models.`name`, prices.`name`)>0 LIMIT 1); + SELECT price_id, price, model_id FROM prices LEFT JOIN models USING(model_id); рещение проблемы?
     
  20. Gromo

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

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    inline
    если правильно применишь - да.
     
  21. Mark32

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

    С нами с:
    15 июн 2008
    Сообщения:
    539
    Симпатии:
    2
    Уважаемые, помогите пожалуйста разобраться с одной простой вещью:

    делаю запрос:

    PHP:
    1.  
    2. $sql = "UPDATE $table SET data1 = '$data1', data2 = '$data2' WHERE data3 = '$data3'";
    3. mysql_query("SET NAMES 'utf8'");
    4.  
    5. //далее проверяем на выполнение и собственно выполняем
    6.  
    7. if (!mysql_query($sql)) { echo mysql_error();} else {echo "$data3 - ok";}
    Короче всегда возвращает что операция выполнена, даже если data3 не содержит $data3

    Подскажите пожалуйста где ошибка :(
     
  22. Gromo

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

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    Mark32
    код правильный, логика неправильная.
    проверяй значение $data1, $data2, $data3, а то ведь можно и sql-injection прихватить
     
  23. Mark32

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

    С нами с:
    15 июн 2008
    Сообщения:
    539
    Симпатии:
    2
    хм. Со значениями всё нормально, распечатал запрос - всё путём..
     
  24. Mark32

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

    С нами с:
    15 июн 2008
    Сообщения:
    539
    Симпатии:
    2
    сунул запросы в pma - чтоб "напрямик"

    в итоге всё нормально - там где в data3 нет $data3 мускул пишет: # MySQL вернула пустой результат (т.е. ноль строк).
    что абсолютно точно, но почему если он выдаёт пустой результат, считается что всё же выполнена операция апдейта?
     
  25. Gromo

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

    С нами с:
    24 май 2010
    Сообщения:
    2.786
    Симпатии:
    2
    Адрес:
    Ташкент
    Mark32
    mysql_query($sql) возвращает false только в случае ошибки. а так хоть и обновилось 0 строк, ошибок-то не было.