2014-01-19 5 views
0

На моем веб-сайте были вложенные запросы, которые сохраняли результаты, и в итоге мне стало сложно, так как мой код стал больше. Я пытаюсь научиться присоединяться к таблицам и делать подзапросы, чтобы упростить мой код. Этот запрос возвращает точную информацию, в которой я нуждаюсь, но время загрузки страницы менялось с 1 секунды до 9 секунд после добавления этого запроса. Есть ли способ ускорить это, или есть что-то, что мне не хватает в нем, что заставляет его так долго?Mysqli присоединился к запросу очень медленно

SELECT p.product_id, 
     p.product_name, 
     p.product_pic, 
     AVG(r.review_stars), 
     COUNT(DISTINCT r.review_id), 
     (SELECT c.price_price FROM prices as c WHERE c.price_product=p.product_id ORDER BY c.price_price ASC LIMIT 1), 
     (SELECT c.price_vendor FROM prices as c WHERE c.price_product=p.product_id ORDER BY c.price_price ASC LIMIT 1) as VID, 
     p.product_url, 
     p.product_clicks, 
     SUM(c.price_clicks), 
     COUNT(c.price_price), 
     c.price_affiliate, 
     (SELECT v.vendor_name FROM vendors as v WHERE v.vendor_id=VID LIMIT 1) 
FROM products as p 
LEFT OUTER JOIN reviews as r ON p.product_id = r.review_product 
LEFT OUTER JOIN prices as c ON c.price_product = p.product_id 
GROUP BY p.product_id 
ORDER BY p.product_clicks DESC 
LIMIT 21 
+0

Опубликовать структуры таблиц – Sara

+0

Это медленно, потому что вы используете множество подзапросов, которые зависят от основного запроса. Это 3 подзапроса, чтобы получить цены. Price_price, prices.price_vendor, vendors.vendor_name. Вы можете ускорить запрос, получив другую информацию, а затем присоедините к набору результатов цены и поставщики, чтобы вытащить эти биты информации. – vidaica

ответ

0

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

SELECT 

main_results.*, 

(SELECT c.price_price FROM prices as c WHERE c.price_product=main_results.product_id ORDER BY c.price_price ASC LIMIT 1), 
(SELECT c.price_vendor FROM prices as c WHERE c.price_product=main_results.product_id ORDER BY c.price_price ASC LIMIT 1) as VID, 
(SELECT v.vendor_name FROM vendors as v WHERE v.vendor_id=VID LIMIT 1) 

FROM 

(

    SELECT p.product_id, 
      p.product_name, 
      p.product_pic, 
      AVG(r.review_stars), 
      COUNT(DISTINCT r.review_id),     
      p.product_url, 
      p.product_clicks, 
      SUM(c.price_clicks), 
      COUNT(c.price_price), 
      c.price_affiliate    
    FROM products as p 
    LEFT OUTER JOIN reviews as r ON p.product_id = r.review_product 
    LEFT OUTER JOIN prices as c ON c.price_product = p.product_id 
    GROUP BY p.product_id 
    ORDER BY p.product_clicks DESC 
    LIMIT 21 

) AS main_results 
0

Возможно, вы можете сделать его еще быстрее код этого vidaica в.

товарам потребуется ИНДЕКС (product_clicks, product_id); то посмотрите, не дает ли это вам необходимых идентификаторов:

SELECT product_id FROM products ORDER BY product_clicks DESC LIMIT 21;

Заменить эту строку:

из продуктов, как р

с

FROM (SELECT product_id из продуктов ORDER BY product_clicks DESC LIMIT 21), как идентификаторы РЕГИСТРИРУЙТЕСЬ продукты р = О p.product_id ids.product_id

(Там может быть несколько больше настроек, необходимых, например, удаление внешней границы.)

Принцип его предложения состоит в том, чтобы уничтожить данные только до 21 строки, прежде чем делать подзапросы. Я сделал еще один шаг вперед, также избегая JOINs, пока не будет только 21. Кроме того, INDEX, который я выбрал, позволяет сканировать в INDEX, а не попасть в таблицу, чтобы найти product_clicks.

См. EXPLAIN для «Использование индекса».

Смежные вопросы