выполнение запроса mysql занимает более 1 минуты

#php #mysql

Вопрос:

этот запрос

 SELECT * FROM kp_landing_page lp  WHERE lp.parent = '7' AND (  SELECT COUNT(*) FROM kp_landing_page_product lpp  WHERE lpp.landing_page_id = lp.landing_page_id  AND lpp.productid = '6176'  ) != 0  

для завершения требуется около 1 минуты, я попытался переписать его следующим образом

 SELECT * FROM kp_landing_page lp  INNER JOIN (SELECT COUNT(*) FROM kp_landing_page_product lpp  WHERE lpp.landing_page_id = lp.landing_page_id  AND lpp.productid = '6176') != 0  WHERE lp.parent = '7'  

Хотя это намного быстрее (3-4 секунды), он не получает необходимых данных, которые мне нужны, даже если все таблицы остаются прежними, и выполнение этого запроса внутри phpmyadmin дает мне те же данные, что и старый. это просто выдает мне следующую ошибку

 The current selection does not contain a unique column.   Functions such as raster edits, checkboxes, Edit,   Copy and Delete are not available.  

Есть идеи о том, как это оптимизировать? не обязательно быть безумно быстрым прямо сейчас, замедляясь на 1 минуту.

Редактировать

Запуск объяснения по старому запросу

 EXPLAIN SELECT * FROM kp_landing_page lp WHERE lp.parent = '7'  AND ( SELECT COUNT(*) FROM kp_landing_page_product lpp  WHERE lpp.landing_page_id = lp.landing_page_id  AND lpp.productid = '6176' ) != 0  

дает мне следующее

 1 id PRIMARY select_Type lp table ALL type  NULL possible_keys  NULL keys NULL key_len NULL ref 233 rows Using where extra --- 2 DEPENDENT SUBQUERY lpp ref landing_page_id landing_page_id 4 kerstpakketonline.lp.landing_page_id 437 Using where  

EDIT 2

some more information

this piece of code (PHP) is where the slowdown happens

 $landingPages = array();  $qGetMainPages = $connection-gt;query("SELECT *  FROM kp_landing_page WHERE parent = 0");   foreach ($qGetMainPages-gt;rows as $mainPage) {  $qGetSubPages = $connection-gt;query("  SELECT lp.* FROM kp_landing_page lp  WHERE lp.parent = '" . (int)$mainPage['landing_page_id'] . "' AND (  SELECT COUNT(*) FROM kp_landing_page_product lpp  WHERE lpp.landing_page_id = lp.landing_page_id   AND lpp.productid = " . (int)$row['productID'] . "  ) != 0  ");    foreach ($qGetSubPages-gt;rows as $subPage) {  $landingPages[$mainPage['title']][] = $subPage['title'];  }  }   

seems to be executing x amount of queries foreach product thus causing o(n) issues?

EDIT 3

using SHOW CREATE TABLE on both tables

— kp_landing_page_product

kp_landing_page_product CREATE TABLE kp_landing_page_product ( id int(11) NOT NULL AUTO_INCREMENT, landing_page_id int(11) NOT NULL, productid int(11) NOT NULL, PRIMARY KEY (id), KEY landing_page_id (landing_page_id), KEY productid (productid), CONSTRAINT landing_page_id_2 FOREIGN KEY (landing_page_id) REFERENCES kp_landing_page (landing_page_id) ON DELETE CASCADE ) ENGINE=InnoDB AUTO_INCREMENT=522630 DEFAULT CHARSET=utf8

— kp_landing_page

kp_landing_page CREATE TABLE kp_landing_page (  landing_page_id int(11) NOT NULL AUTO_INCREMENT,  title varchar(255) COLLATE utf8mb4_bin NOT NULL,  title_multi varchar(255) COLLATE utf8mb4_bin NOT NULL,  rewrite varchar(255) COLLATE utf8mb4_bin NOT NULL,  active tinyint(4) NOT NULL DEFAULT 1,  parent int(11) NOT NULL DEFAULT 0,  ordering int(11) NOT NULL,  show_as_filter tinyint(4) NOT NULL DEFAULT 0,  popular tinyint(4) NOT NULL DEFAULT 0, color_code varchar(255) COLLATE utf8mb4_bin NOT NULL,  PRIMARY KEY (landing_page_id) ) ENGINE=InnoDB AUTO_INCREMENT=247 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

kp_landing_page_продукт содержит 160854 всего строк

страница kp_landing_page содержит всего 233 строки

kp_landing_page возвращает 9 строк с помощью этого SELECT * FROM kp_landing_page WHERE parent = 0 запроса

kp_landing_page_продукт возвращает около 40 строк с помощью этого

SELECT * FROM kp_landing_page lp WHERE lp.parent = '7' AND ( SELECT COUNT(*) FROM kp_landing_page_product lpp WHERE lpp.landing_page_id = lp.landing_page_id AND lpp.productid = '6176' ) != 0 запрос, это может измениться в зависимости от поставляемого продукта

Комментарии:

1. Что дает эту ошибку? Похоже, это не ошибка MySQL.

2. Если lp.parent является целым числом, почему вы используете '7' вместо просто 7?

3. О чем говорит вам план выполнения? Может быть, вам не хватает индексов?

4. @ysth phpMyAdmin выдает эту ошибку

5. @SalmanA это просто потому, что запрос строится динамически с помощью PHP

Ответ №1:

Индексы:

 lp: INDEX(landing_page_id) lpp: INDEX(landing_page_id, productid) -- either order is OK  

Используйте EXISTS (он же «полу-соединение») вместо

 AND (  SELECT COUNT(*) FROM kp_landing_page_product lpp  WHERE lpp.landing_page_id = lp.landing_page_id  AND lpp.productid = '6176'  ) != 0  

—gt;

 AND EXISTS ( SELECT 1 FROM kp_landing_page_product AS lpp  WHERE lpp.landing_page_id = lp.landing_page_id  AND lpp.productid = '6176' )  

EXISTS остановится, когда будет найден первый; COUNT(*) вероятно, придется проделать больше работы, чтобы узнать точное количество.

(Если вы хотите продолжить обсуждение, пожалуйста, укажите SHOW CREATE TABLE две таблицы, размер каждой таблицы (приблизительное количество строк) и количество строк, возвращаемых запросом.)

Комментарии:

1. Эй, используй свой AND EXISTS … запрос выдает мне ошибку #1064 - There is something wrong in the syntax used at ''in line 5 , также я обновлю свой пост с вашей необходимой информацией

2. Покажите мне запрос в том виде, в каком он у вас есть сейчас.

3. ` ВЫБЕРИТЕ * ИЗ страницы kp_landing_page lp, ГДЕ lp.parent = ‘» . $Главная страница[‘landing_page_id’] . «‘ И СУЩЕСТВУЕТ ( ВЫБЕРИТЕ 1 ИЗ kp_landing_page_product КАК lpp, ГДЕ lpp.landing_page_id = lp.landing_page_id И lpp.productid = ‘» . $строка[‘ProductID’]. «‘) `

4. I предложение WHERE перед в AND EXISTS противном случае я получил бы синтаксическую ошибку

5. @nielsvanhoof — Нет. WHERE может иметь два «выражения» AND'd вместе. EXISTS ( SELECT ... ) это «выражение». Должно быть, что-то еще не так. Давайте посмотрим запрос после того, как PHP закончит его сборку.