douyueqing1530 2016-06-02 19:36
浏览 163
已采纳

使用我的rest API,性能低下并超时

I am hosting a restful API created using Silex (a PHP micro-framework based on Symfony). Following this tutorial, this API returns json objects depending on the parameters. However some queries are so low that OVH's timeout kicks in and I get the following message :

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

Although some of my SQL queries are a bit long (up to 8-12 lines), they aren't that complex and I don't understand why the performance is that low.

Is there anything I can do to speed it up, and to avoid being timed out by OVH ? I am querying every items using solely one SQL request (thus being long sometimes), and various operators (WHERE, several AND/OR, IN...).

Here's an example of a SQL query which takes forever to get :

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
                )
        )

Still having performance issues. My code went from this :

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' )))))) 

to this :

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' ) 

Should I use "faster" joins ? How can I optimize those queries ?

EDIT : EXPLAIN array from MySQL :

Explain from MySQL database for the query above

  • 写回答

1条回答 默认 最新

  • dongshi2588 2016-06-02 20:03
    关注

    To get you started cleaning this up - Please note query is incomplete. This should be faster because you are not nesting selects.

    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];
    

    Once you have completed with joins - use Explain. EXPLAIN SELECT staff.* FROM ... which will help you to see where the query is running slow because chances are you are missing some indexes.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 如何通过代码传输视频到亚马逊平台
  • ¥15 php查询mysql数据库并显示至下拉列表中
  • ¥15 freertos下使用外部中断失效
  • ¥15 输入的char字符转为int类型,不是对应的ascall码,如何才能使之转换为对应ascall码?或者使输入的char字符可以正常与其他字符比较?
  • ¥15 devserver配置完 启动服务 无法访问static上的资源
  • ¥15 解决websocket跟c#客户端通信
  • ¥30 Python调用dll文件输出Nan重置dll状态
  • ¥15 浮动div的高度控制问题。
  • ¥66 换电脑后应用程序报错
  • ¥50 array数据同步问题