Mysql查询真的很慢

时间:2017-10-31 10:43:47

标签: mysql sql

今天刚刚测试了大型数据集。我的查询确实表现不佳,我怀疑是因为子查询。这是我的查询(MYSQL PDO:)

SELECT  a.data_id,a.data_name,a.data_parent_id,a.data_type,a.data_return_text,a.data_description,
IF ((length(a.data_id)<=1), 0,
CASE a.data_type
WHEN '0' 
THEN 
IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND client_id=:client_id),0)
WHEN '1' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND client_id=:client_id),0)
WHEN '2' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND client_id=:client_id),0)
WHEN '3' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND client_id=:client_id),0)
WHEN '4' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '0' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('1','0') AND client_id=:client_id),0)
WHEN '5' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '0' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('1','0') AND client_id=:client_id),0)
WHEN '6' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '0' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('1','0') AND client_id=:client_id),0)
WHEN '7' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND client_id=:client_id),0)
WHEN '8' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '0' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('1','0') AND client_id=:client_id),0)
WHEN '9' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND client_id=:client_id),0)
WHEN '10' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND client_id=:client_id),0)
WHEN '11' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '0' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('1','0') AND client_id=:client_id),0)
WHEN '12' THEN 
IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND client_id=:client_id),0)
WHEN '13' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '0' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('1','0') AND client_id=:client_id),0)
WHEN '14' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '0' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('1','0') AND client_id=:client_id),0)
WHEN '15' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '0' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('1','0') AND (DATE(trans_date) <= DATE(NOW())) AND client_id=:client_id),0)
WHEN '16' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND (DATE(trans_date) <= DATE(NOW())) AND client_id=:client_id),0)
WHEN '17' THEN
IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND client_id=:client_id),0)
END) as total 
FROM data_list a
LEFT JOIN data_transaction_log b
ON b.trans_data_id = a.data_id
WHERE a.client_id=:client_id
GROUP   BY a.data_name
ORDER BY a.data_id asc

[说明]

有表格:

  1. 表:DATA_LIST
  2. 包含大约24种仪器,仪器在使用时会创建一个事务日志。它将产生(值)及其(+ ve或-ve符号)及其日期戳

    1. 表:data_transaction_log
    2. 此表将记录data_list中仪器的每个结果。

      table:data_list 的结果将在此表中记录:

      • (value)=&gt; trans_value
      • (+ ve符号将记录为0&amp; -ve符号将记录为1)=&gt; TRANS_TYPE
      • (日期)=&gt; TRANS_DATE

      [意向]

      1. 我想得到+ ve&amp;的总和 - 每种工具的每笔交易的价值:

        IFNULL((SELECT SUM(trans_value * case trans_type when'1',然后是-1 else 1 end)FROM data_transaction_log WHERE trans_data_id = a.data_id和trans_type in('0','1')AND client_id =:client_id) ,0)

      2. 某些工具有特殊条件(案例15和16),需要日期条件。

        IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND (DATE(trans_date) <= DATE(NOW())) AND client_id=:client_id),0)
        

        [问题}

        在低数据集大约100(在data_transaction_log中)它可以正常工作。但是超过1k它真的很慢!

        请指导我。

        谢谢!

1 个答案:

答案 0 :(得分:1)

对于data_list数据类型字段,多个值具有相同的精确结果。例如,WHEN a.data_type IN ('0', '1', '2', '3', '7', '9', '10', '12', '17')

你有相同的结果:

IFNULL((SELECT SUM(trans_value * case trans_type when '1' then -1 else 1 end) FROM data_transaction_log WHERE trans_data_id = a.data_id and trans_type in ('0','1') AND client_id=:client_id),0)

我认为它不会使代码更快,但编写的代码更少,更容易调试:

SELECT a.data_id,a.data_name,a.data_parent_id,a.data_type
      ,a.data_return_text,a.data_description
      ,CASE WHEN length(a.data_id)<=1) 
             THEN 0

            WHEN a.data_type IN ('0', '1', '2', '3', '7', '9', '10', '12', '17')
             THEN IFNULL((SELECT SUM(trans_value * case WHEN trans_type = '1' THEN -1 else 1 end) 
                            FROM data_transaction_log 
                           WHERE trans_data_id = a.data_id and trans_type in ('0','1') 
                             AND client_id=:client_id)
                           ,0)            

            WHEN a.data_type IN ('4', '5', '6', '8', '11', '13', '14')
             THEN IFNULL((SELECT SUM(trans_value * case WHEN trans_type = '0' then -1 else 1 end) 
                            FROM data_transaction_log 
                           WHERE trans_data_id = a.data_id and trans_type in ('0','1') 
                             AND client_id=:client_id)
                           ,0)

            WHEN a.data_type IN ('15', '16') 
             THEN IFNULL((SELECT SUM(trans_value * case WHEN trans_type = '0' then -1 else 1 end) 
                            FROM data_transaction_log 
                           WHERE trans_data_id = a.data_id and trans_type in ('0','1') 
                             AND (DATE(trans_date) <= DATE(NOW())) AND client_id=:client_id)
                           ,0)

       END as total 
  FROM data_list a LEFT JOIN data_transaction_log b ON b.trans_data_id = a.data_id
 WHERE a.client_id=:client_id
GROUP BY a.data_name
ORDER BY a.data_id asc

-

第二次采取:

为了解决这个问题,最好知道为什么要检查IFNULL。如果由于左连接返回NULL而连接条件不匹配,那么您可以通过检查左连接表中的主键data_transaction_log,再一步简单地算法一步,对于NULL ...主键不应为null,如果为null,则左键必须为NULL。在原始算法中,您给NULL结果值为0:

SELECT a.data_id,a.data_name,a.data_parent_id,a.data_type
      ,a.data_return_text,a.data_description
      ,CASE WHEN b.<PRIMARYKEY> IS NULL
             THEN 0
            WHEN length(a.data_id)<=1) 
             THEN 0    
            WHEN a.data_type IN ('0', '1', '2', '3', '7', '9', '10', '12', '17')
             THEN (SELECT SUM(trans_value * case WHEN trans_type = '1' THEN -1 else 1 end) 
                     FROM data_transaction_log 
                    WHERE trans_data_id = a.data_id and trans_type in ('0','1')                             AND client_id=:client_id)                      

            WHEN a.data_type IN ('4', '5', '6', '8', '11', '13', '14')
             THEN (SELECT SUM(trans_value * case WHEN trans_type = '0' then -1 else 1 end) 
                     FROM data_transaction_log 
                    WHERE trans_data_id = a.data_id and trans_type in ('0','1') 
                      AND client_id=:client_id)                   

            WHEN a.data_type IN ('15', '16') 
             THEN (SELECT SUM(trans_value * case WHEN trans_type = '0' then -1 else 1 end) 
                     FROM data_transaction_log 
                    WHERE trans_data_id = a.data_id and trans_type in ('0','1') 
                      AND (DATE(trans_date) <= DATE(NOW())) AND client_id=:client_id)                  

       END as total 
  FROM data_list a LEFT JOIN data_transaction_log b ON b.trans_data_id = a.data_id
 WHERE a.client_id=:client_id
GROUP BY a.data_name
ORDER BY a.data_id asc