2016-06-02 2 views
0

Я размещаю restful API, созданный с использованием Silex (микроструктура PHP на основе Symfony). Следуя this tutorial, этот API возвращает объекты json в зависимости от параметров. Однако некоторые запросы настолько низки, что тайм-аут пинки OvH в в и я получаю следующее сообщение:Низкая производительность и тайм-аут с моим отдыхом API

SQLSTATE[HY000]: General error: 2013 Lost connection to MySQL server during query

Хотя некоторые из моих запросов SQL немного длинные (до 8-12 строк), они не являются, что комплекс и я не понимаю, почему производительность низкая.

Есть ли что-нибудь, что я могу сделать, чтобы ускорить его, и чтобы избежать времени от OVH? Я запрашиваю все элементы, используя только один запрос SQL (таким образом, иногда это длинный), и различные операторы (ГДЕ, несколько И/ИЛИ, В ...).

Вот пример запроса SQL, который принимает навсегда для того чтобы получить:

SELECT * 
FROM staff 
WHERE staff_id IN (
     SELECT host_id 
     FROM class_host 
     WHERE class_id IN (
       SELECT class_id 
       FROM class 
       WHERE classroom_id IN (
         SELECT classroom_id 
         FROM classroom 
         WHERE classroom_gps_lat BETWEEN $ARRAY_VALEUR [0] 
           AND $ARRAY_VALEUR [2] 
          AND classroom_gps_lon BETWEEN $ARRAY_VALEUR [1] 
           AND $ARRAY_VALEUR [3] 
         ) 
       ) 
     ) 
    OR staff_id IN (
     SELECT teacher_id 
     FROM class_teacher 
     WHERE class_id IN (
       SELECT class_id 
       FROM class 
       WHERE classroom_id IN (
         SELECT classroom_id 
         FROM classroom 
         WHERE classroom_gps_lat BETWEEN $ARRAY_VALEUR [0] 
           AND $ARRAY_VALEUR [2] 
          AND classroom_gps_lon BETWEEN $ARRAY_VALEUR [1] 
           AND $ARRAY_VALEUR [3] 
         ) 
       ) 
     ) 
    AND class_id IN (
     SELECT class_id 
     FROM class_teacher 
     WHERE teacher_id IN (
       SELECT staff_id 
       FROM staff 
       WHERE staff_name LIKE $QUOTEDARRAY 
       ) 
     ) 

Тем не менее, имеющих проблемы с производительностью. Мой код пошел от этого:

SELECT Count(*) AS COUNT 
FROM staff 
WHERE staff_id IN (SELECT host_id 
        FROM class_host 
        WHERE (class_id IN (SELECT class_id 
              FROM class 
              WHERE classroom_id IN (SELECT 
               classroom_id 
                    FROM 
               classroom 
                    WHERE 
               region_id IN ('FR')))) 
          OR staff_id IN (SELECT teacher_id 
              FROM class_teacher 
              WHERE class_id IN (SELECT class_id 
                   FROM class 
                   WHERE 
                classroom_id IN (SELECT 
                classroom_id 
                    FROM 
                classroom 
                    WHERE 
                region_id IN (SELECT 
                region_id 
                   FROM region 
                   WHERE 
                region_country_code IN ( 
                'FR')))))) 

к этому:

SELECT Count(*) AS COUNT 
FROM staff 
     JOIN class_host 
     ON staff.staff_id = class_host.host_id 
     JOIN class AS class1 
     ON class_host.class_id = class1.class_id 
     JOIN classroom AS classroom1 
     ON class1.classroom_id = classroom1.classroom_id 
     JOIN region AS region1 
     ON classroom1.region_id = region1.region_id 
     JOIN class_teacher 
     ON staff.staff_id = class_teacher.teacher_id 
     JOIN class AS class2 
     ON class_teacher.class_id = class2.class_id 
     JOIN classroom AS classroom2 
     ON class2.classroom_id = classroom2.classroom_id 
     JOIN region AS region2 
     ON classroom2.region_id = region2.region_id 
WHERE region1.region_country_code IN ('FR') 
     AND region2.region_country_code IN ('FR') 

Должен ли я использовать "быстрее" присоединяется? Как я могу оптимизировать эти запросы?

EDIT: EXPLAIN массив из MySQL:

Explain from MySQL database for the query above

+0

Не связанный с вашей проблемой, но для любви к печенью, пожалуйста * отформатируйте свои запросы! * И для вашего собственного здравомыслия, и для нас. – Siyual

+1

Прошу исследовать 'JOIN's. На самом деле нет необходимости в всех подзапросах, которые у вас есть в вашем запросе. – Siyual

+0

Будет делать в будущем @Siyual! И ПРИСОЕДИНИТЕСЬ к этому, спасибо. Я изменю свои запросы и посмотрю, как это происходит. Не уверен, как принять ваш ответ, поскольку он фактически является комментарием, а не фактическим ответом. –

ответ

0

Для начала уборки это до - Пожалуйста, обратите внимание, запрос является неполным. Это должно быть быстрее, потому что вы не выбираете гнездо.

SELECT 
    staff.* 
FROM 
    staff 
    JOIN class_host ON staff.staff_id = class_host.host_id 
    JOIN class ON class_host.class_id = class.class_id 
    JOIN classroom ON classroom.classroom_id = class.classroom_id 
WHERE 
    classroom.gps_lat BETWEEN $ARRAY_VALEUR[0] AND $ARRAY_VALEUR[2] 
    AND classroom.classroom_gps_lon BETWEEN $ARRAY_VALEUR[1] AND $ARRAY_VALEUR[3]; 

После того, как вы завершили работу с соединениями - используйте Explain. EXPLAIN SELECT staff.* FROM ..., который поможет вам увидеть, где выполняется запрос, потому что, скорее всего, вам не хватает некоторых индексов.

+0

Спасибо, мне еще многое предстоит узнать о структуре SQL. Я не думал о выборе вложенности и просто конкатенировал запросы. Я попробую это и посмотрю, увеличивается ли производительность. –

+0

Взгляните на это для объяснения того, что такое 'inner join'. http://www.mysqltutorial.org/mysql-inner-join.aspx – Gravy

+0

У меня все еще проблемы с производительностью; редактируя верхнюю почту, чтобы получить прибыль от форматирования кода, я не уверен, что я делаю права присоединения –

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