Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770
Форумы портала PHP.SU :: Версия для печати :: Долго выполняется запрос что можно предпринять
Форумы портала PHP.SU » PHP » SQL и Архитектура БД » Долго выполняется запрос что можно предпринять

Страниц (3): [1] 2 3 »
 

1. 3d_killer - 21 Марта, 2016 - 11:37:47 - перейти к сообщению
Написал БД для недвижимости, на любом итпе объекта может быть сколько угодно параметров которые берутся из справочников, взял добавил рандомно 50 тыс записей,
при вводе нового объекта срабатывает поиск на соответствие, так вот если параметров не было показывает общее количество объектов и с лимитом немного объектов.
Так вот первый раз это происходит минуты 2, потом справляется за пол секунды, но стоит внести новый объект то опять первый раз около 2х минут, можно как это решить?

запрос большой много LEFT JOIN для выдергивания параметров, пример:

CODE (SQL):
скопировать код в буфер обмена
  1.  
  2. SELECT `RS-CMS_adresat_object`.*, `dir_param_ws`.value AS param_ws , `param_test`.value_int AS param_test , `dir_param_floor`.value_int AS param_floor , `dir_param_material`.value AS param_material , `param_s_k`.value_int AS param_s_k , `param_rrr`.value_int AS param_rrr , `dir_param_names`.value AS param_names , `param_info`.value AS param_info , `param_price`.value_int AS param_price , `dir_param_city`.value AS param_city FROM `RS-CMS_adresat_object` LEFT JOIN `RS-CMS_adresat_directory_values_to_object` AS `param_ws` ON `param_ws`.object_id = `RS-CMS_adresat_object`.id AND `param_ws`.id_directory=16 LEFT JOIN `RS-CMS_adresat_directory_values` AS `dir_param_ws` ON `dir_param_ws`.id = `param_ws`.link AND `dir_param_ws`.id_directory=16 LEFT JOIN `RS-CMS_adresat_directory_values_to_object` AS param_test ON `param_test`.object_id = `RS-CMS_adresat_object`.id AND `param_test`.id_directory=19 LEFT JOIN `RS-CMS_adresat_directory_values_to_object` AS `param_floor` ON `param_floor`.object_id = `RS-CMS_adresat_object`.id AND `param_floor`.id_directory=14 LEFT JOIN `RS-CMS_adresat_directory_values` AS `dir_param_floor` ON `dir_param_floor`.id = `param_floor`.link AND `dir_param_floor`.id_directory=14 LEFT JOIN `RS-CMS_adresat_directory_values_to_object` AS `param_material` ON `param_material`.object_id = `RS-CMS_adresat_object`.id AND `param_material`.id_directory=15 LEFT JOIN `RS-CMS_adresat_directory_values` AS `dir_param_material` ON `dir_param_material`.id = `param_material`.link AND `dir_param_material`.id_directory=15 LEFT JOIN `RS-CMS_adresat_directory_values_to_object` AS param_s_k ON `param_s_k`.object_id = `RS-CMS_adresat_object`.id AND `param_s_k`.id_directory=20 LEFT JOIN `RS-CMS_adresat_directory_values_to_object` AS param_rrr ON `param_rrr`.object_id = `RS-CMS_adresat_object`.id AND `param_rrr`.id_directory=22 LEFT JOIN `RS-CMS_adresat_directory_values_to_object` AS `param_names` ON `param_names`.object_id = `RS-CMS_adresat_object`.id AND `param_names`.id_directory=23 LEFT JOIN `RS-CMS_adresat_directory_values` AS `dir_param_names` ON `dir_param_names`.id = `param_names`.link AND `dir_param_names`.id_directory=23 LEFT JOIN `RS-CMS_adresat_directory_values_to_object` AS param_info ON `param_info`.object_id = `RS-CMS_adresat_object`.id AND `param_info`.id_directory=17 LEFT JOIN `RS-CMS_adresat_directory_values_to_object` AS param_price ON `param_price`.object_id = `RS-CMS_adresat_object`.id AND `param_price`.id_directory=24 LEFT JOIN `RS-CMS_adresat_directory_values_to_object` AS `param_city` ON `param_city`.object_id = `RS-CMS_adresat_object`.id AND `param_city`.id_directory=10 LEFT JOIN `RS-CMS_adresat_directory_values` AS `dir_param_city` ON `dir_param_city`.id = `param_city`.link AND `dir_param_city`.id_directory=10 WHERE `RS-CMS_adresat_object`.type_id=:type GROUP BY `RS-CMS_adresat_object`.id ORDER BY `RS-CMS_adresat_object`.date_add DESC LIMIT 10

(Добавление)
на хосте проверил занимает 33 секунды это дело, но все равно это очень долго для 50 тыс объектов
(Добавление)
на сколько я понял запрос возникает длительный если происходит запрос без условий, если есть хоть одно условие помимо WHERE `RS-CMS_adresat_object`.type_id=:type то все происходит быстро
2. Viper - 21 Марта, 2016 - 15:28:06 - перейти к сообщению
Что с индексами по выбираемым полям?
EXPLAIN вам в помощь
3. OrmaJever - 21 Марта, 2016 - 16:13:34 - перейти к сообщению
Я конечно всё понимаю, но тут 15 лефт джоинов (15 карл!!!), может в этом проблема?
4. 3d_killer - 21 Марта, 2016 - 16:23:17 - перейти к сообщению
OrmaJever а как я еще получу кучу параметров из других таблиц?
5. 3d_killer - 21 Марта, 2016 - 16:30:18 - перейти к сообщению
Добавил пару индексов пока не могу проверить
6. tuareg - 21 Марта, 2016 - 16:38:22 - перейти к сообщению
Нужно разобраться с using filesort + using temporary
а так все у Вас нормально.
7. T1grOK - 21 Марта, 2016 - 20:08:50 - перейти к сообщению
Все дело в сортировке (да и вездесущие LEFT JOIN ничего хорошего не принесут). Сортировка, слияние результатов таблиц(join merge) очень дорогое удовольствие.
Смотрите SHOW STATUS.
Скорей всего в буферы не помещается результат - sort_buffer_size, tmp_table_size, max_heap_table_size и т.д. Зависит от результата SHOW STATUS и используемого движка.
P.S. Даже, если все будет помещаться в буферы, то врят ли удастся получить приемлемое время выполнения. Здесь несколько путей:
- повысить процессорную мощь и более производительную подсистему хранения использовать(SSD)
- разбить запрос на несколько мелких
- денормализовать БД
- установить Sphinx и скормить данные ему.
8. tuareg - 21 Марта, 2016 - 22:14:29 - перейти к сообщению
Тот эксплейн, видно же что он не совсем тот. Ну не может быть при таком эксплейне время 33 секунды.( там что индусы вручную сортируют?) Ну да 15 left join, но это не не так критично.
Там либо правда очень медленное железо, но это просто проверяется. Либо кто-то кого-то обманывает Улыбка
Сам по себе запрос не страшен. Тяжел но не страшен. Не надо бояться join-ов.
Сфинкс здесь вообще причем? Денормализация тоже вряди, видно же что это движок какой-то. Что тут денормализуешь? Мелкие запросы это да возможно ... .
type_id хорошо отсекает там всего 3 записи.
9. 3d_killer - 21 Марта, 2016 - 23:31:31 - перейти к сообщению
с ключами шевелится быстро, но до первого инсерта, потом похоже переиндексация, первый запрос тупит, а данных надо добавлять много
(Добавление)
движок MyIsam, на InnoDb тупит еще больше
(Добавление)
я даже низнаю что будет когда данными наполнится таблица RS-CMS_adresat_directory_values_ to_object она по идее раз в 15 больше из которой делаю основной селект, сейчас она пустая практически
10. Viper - 21 Марта, 2016 - 23:46:40 - перейти к сообщению
3d_killer пишет:
с ключами шевелится быстро, но до первого инсерта, потом похоже переиндексация, первый запрос тупит, а данных надо добавлять много
говорите конкретнее. "шевелится быстро" понятие растяжимое. приведите конфу железа и реальные цифры, а не мифическое "уминя ничево неработает!!111 миня всиво ажтрисет!!11"
11. tuareg - 22 Марта, 2016 - 07:04:48 - перейти к сообщению
проверьте на локальном хосте. Движок MyIsam не может быть быстрей(ладно намного быстрей) чем InnoDB. Скорей всего это "кривая" настройка или слабое железо, мало памяти
12. T1grOK - 22 Марта, 2016 - 07:12:03 - перейти к сообщению
3d_killer пишет:
с ключами шевелится быстро, но до первого инсерта

Mysql помещает результаты запросов в кеш и при повторных запросах отдает из кеша. При вставке или обновлении записей кеш сбрасывается.
13. 3d_killer - 22 Марта, 2016 - 08:11:04 - перейти к сообщению
на локальном хосте под openserver
SSD 512 запись чтение, проц i3 2,8 4 ядра, 8 гигов оперативы, но нагрузки я не замечал,
база построена на PDO может попробовать Postgre поставить?
(Добавление)
что то подключил через postgre а оно вобще не пашет, подключается без ошибок но запросы не выполняет, вот например
PHP:
скопировать код в буфер обмена
  1. $query="
  2.         CREATE TABLE IF NOT EXISTS `core_action` (
  3.         `id` int(11) NOT NULL AUTO_INCREMENT COMMENT 'Уникальный ID',
  4.         `id_module` int(11) DEFAULT NULL COMMENT 'id модуля',
  5.         `name_ru` varchar(250) NOT NULL COMMENT 'Имя модуля рус',
  6.         `name_en` varchar(250) NOT NULL COMMENT 'Имя операции (функции)',
  7.         `access` int(1) DEFAULT '0',
  8.                 PRIMARY KEY (`id`),
  9.                 UNIQUE INDEX `name_en` (`name_en`)
  10.         ) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8;";
  11.                 $STH1=DB::DBH()->prepare($query);
  12.                 $STH1->execute();      
  13.                 $STH=DB::DBH()->prepare("SHOW TABLE STATUS");
  14.                 $STH->execute();
  15.                 $R=$STH->fetchAll();
  16.                 var_dump($R);


вот эта операция не выдает никаких ошибок, но в конце вардамп дает
array (size=0)
empty
(Добавление)
само подключение
PHP:
скопировать код в буфер обмена
  1. defined("RS_ACCESS") or die("Нельзя получить прямой доступ к файлу!");
  2. class DB
  3.         {
  4.         private static $DBH=NULL;
  5.         public static function DBH()
  6.         {
  7.                 if (!self::$DBH)
  8.                         {
  9.                         try
  10.                         {
  11.                         //Префикс базы данных
  12.                         define (PDB,"RS-");
  13.                         //ХОСТ
  14.                         $host="127.0.0.1";
  15.                         //Имя базы
  16.                         $db="new";
  17.                         //Логин
  18.                         $user="root";
  19.                         //Пароль
  20.                         $pass="";
  21.                         //Попытка подключения
  22. self::$DBH=new PDO(sprintf("pgsql:host=%s;port=5432;dbname=%s", $host, $db), $user, $pass);
  23.                         self::$DBH->query("SET NAMES 'utf8'");
  24.                         }
  25.                         catch(PDOException $e)
  26.                         {
  27.                                 echo " Извините. Но операци не может быть выполнена.";
  28.                                 die();
  29.                                 file_put_contents("PDOErrors.txt", $e->getMessage(), FILE_APPEND);
  30.                         }
  31.                         }
  32.                                 return self::$DBH;
  33.                         }
  34.         }


через пгадмин открывается сервер запущен, в чем тут проблема?
14. T1grOK - 22 Марта, 2016 - 09:24:01 - перейти к сообщению
В PostgresSQL нет понятия ENGINE, также нет понятия AUTO_INCREMENT, но есть понятие sequence, который является отдельным объектом в данной СУБД.
P.S. Вы предпочитаете бежать от проблемы, чем решать ее. PostgresSQL по умолчанию настроен таким образом, чтобы запуститься даже на калькуляторе, так что неизбежно придется конфигурировать те или иные параметры.
15. 3d_killer - 22 Марта, 2016 - 09:33:49 - перейти к сообщению
T1grOK, если все же mysql использовать, может проблема в openserver?

 

Powered by ExBB FM 1.0 RC1