如何在sql查询

时间:2016-11-25 04:22:27

标签: mysql sql database performance

如何提高此查询的效果,同时获取所需的所有信息..

SELECT 
    tr.id, tr.request_status, tr.note, tr.created_date, 
    c.name AS customer_name, c.mobile_phONe, 
    u.full_name AS created_by_name, tt.name AS ticket_type_name 
FROM  
    ticket_request tr 
LEFT JOIN 
    ticket_type tt ON tt.id = tr.ticket_type_id 
LEFT JOIN 
    users u ON u.id = tr.created_by 
LEFT JOIN 
    customer c ON c.id = tr.customer_id 
WHERE 
    tr.is_deleted != 1 
    AND tr.user_id IN (SELECT u.id FROM users u WHERE u.status = '1') 
GROUP BY 
    tr.id  
ORDER BY 
    tr.created_date DESC 
LIMIT 0,20 

目前,此查询在7-10秒内运行。

  • ticket_request表有大约100k行
  • customers表有大约300k行
  • users表格和ticket_type没有那么多(约1k行)

5 个答案:

答案 0 :(得分:1)

下面的加速技术是首先取消LIMIT ,只有在此之后,才能完成所有JOINs

SELECT  tr3.id, tr3.request_status, tr3.note, tr3.created_date,
        c.name AS customer_name, c.mobile_phONe,
        u2.full_name AS created_by_name,
        tt.name AS ticket_type_name
    FROM  
    (
        SELECT  tr1.id
            FROM  ticket_request tr1
            JOIN  users u1  ON u1.id = tr1.created_by
            WHERE  u1.status = '1'
              AND  tr1.is_deleted != 1
            ORDER BY  tr1.created_date DESC
            LIMIT  0,20 
    ) AS tr2
    JOIN  ticket_request AS tr3  ON tr3.id = tr2.id
    JOIN  user AS u2 ON u2.id = tr3.created_by
    LEFT JOIN  ticket_type tt  ON tt.id = tr3.ticket_type_id
    LEFT JOIN  customer c  ON c.id = tr3.customer_id
    ORDER BY  tr3.created_date

“衍生”表tr2中的JOINs之后仅触及20行;这是加速的主要原因。

这可能同样好:

SELECT  d.id, d.request_status, d.note, d.created_date,
        c.name AS customer_name, c.mobile_phONe, d.created_by_name,
        tt.name AS ticket_type_name
    FROM  
    (
        SELECT  tr.id AS tr_id, tr.request_status, tr.note, tr.created_date,
                tr.ticket_type_id, tr.customer_id
                u.full_name AS created_by_name
            FROM  ticket_request tr
            JOIN  users u  ON u.id = tr.created_by
            WHERE  u.status = '1'
              AND  tr.is_deleted != 1
            ORDER BY  tr.created_date DESC
            LIMIT  0,20 
    ) AS d
    LEFT JOIN  ticket_type tt  ON tt.id = d.ticket_type_id
    LEFT JOIN  customer c  ON c.id = d.customer_id
    ORDER BY  d.created_date

答案 1 :(得分:0)

我假设您使用的是MySQL。如果没有,可以稍微修改这个答案以适应另一个数据库,但概念应该保持不变。您可以使用ticket_request列向左连接右侧所涉及的所有ID列添加索引:

ALTER TABLE ticket_type ADD INDEX (id);
ALTER TABLE users ADD INDEX (id);
ALTER TABLE customer ADD INDEX (id);      -- important

要解释索引有用的原因,请考虑LEFT JOIN表和ticket_request表之间的第一个ticket_type。如果没有索引,对于ticket_request中的每个记录,数据库必须扫描整个ticket_type表以查找与连接条件匹配的记录。从性能的角度来看,这是昂贵的。但是使用索引,数据库可以更快地完成此操作,因为它“知道”匹配记录的确切位置(或几乎完全准确)。

虽然您提到只有customer表非常大,但您仍然可以将索引添加到其他表中。将来,它们也可能变大。最有可能涉及customer的联接是您查询的瓶颈。

答案 2 :(得分:0)

此处优化的最大机会是使用LIMIT 0,20

  1. GROUP BY tr.id毫无意义,应该删除。

  2. create index ticket_request_ix_is_deleted_created_date on ticket_request (is_deleted,created_date)并将tr.is_deleted != 1更改为tr.is_deleted = 0

    或者

    create index ticket_request_ix_created_date on ticket_request (created_date)

答案 3 :(得分:0)

SELECT 
    tr.id, tr.request_status, tr.note, tr.created_date, 
    c.name AS customer_name, c.mobile_phONe, 
    u.full_name AS created_by_name, tt.name AS ticket_type_name 
FROM  
    ticket_request tr 
LEFT JOIN 
    ticket_type tt ON tt.id = tr.ticket_type_id and tr.is_deleted != 1 
LEFT JOIN 
    users u ON u.id = tr.created_by 
JOIN 
  users u1 ON u1.id  = tr.user_id and u1.status = '1'
LEFT JOIN 
    customer c ON c.id = tr.customer_id 
GROUP BY 
    tr.id  
ORDER BY 
    tr.created_date DESC 
LIMIT 0,20 

尝试此操作可以提高性能并根据您的要求进行调整

答案 4 :(得分:-1)

除了索引之外,在应用程序级别,您可以使用 Memcached (如果您使用的是php)这样的东西。这也将为您带来出色的表现。