是否可以优化此MySql查询

时间:2016-06-06 00:32:18

标签: mysql sql query-optimization

我正在寻找一种优化以下MySQL存储过程的方法:

  DECLARE total BIGINT UNSIGNED;

  DROP TEMPORARY TABLE IF EXISTS tempTable; 
  CREATE TEMPORARY TABLE tempTable(identityValue BIGINT(20) UNSIGNED );

  INSERT INTO tempTable
  SELECT 
    `getIdentity`(samples.`originalId`) 
  FROM 
      `rawData` 
  WHERE 
    `samples`.`groupId` = _group;


  SET total = (

    SELECT 
        IFNULL( SUM(getTotal(rawData.id, NULL, NULL)), 0)

    FROM 
        rawData

    WHERE 
        rawData.user= _user AND
        getIdentity(rawData.id) IN (SELECT * FROM tempTable)

    );


  DROP TEMPORARY TABLE IF EXISTS tempTable; 

  RETURN total;

getIdentity函数如下所示:

RETURN (SELECT IFNULL(MIN(id1), _id)
             FROM `equivalences` WHERE 
             id1 = _id OR id2 = _id);

getTotal函数如下所示:

BEGIN
    DECLARE total INT;

    IF (_startDate IS NULL OR _endDate IS NULL) THEN

        SET total = (SELECT IFNULL(SUM(ops.downloads),0) 
                     FROM objects, ops
                     WHERE objects.id = _objectId AND ops.objectId = _objectId);
    ELSE 
        SET total = (SELECT IFNULL(SUM(ops.downloads),0) 
                     FROM objects, ops
                     WHERE objects.id = _objectId AND ops.objectId = _objectId AND 
                           ops.`date` BETWEEN _startDate AND _endDate);
    END IF;

    RETURN total;
END

现在它需要大约350毫秒才能运行。大多数时候似乎与我正在创建的临时表有关。使用EXPLAIN后,这些表已经包含了我认为必要的索引。

2 个答案:

答案 0 :(得分:1)

我猜你不会将内存用于临时表。尝试

CREATE TEMPORARY TABLE tempTable(identityValue BIGINT(20) UNSIGNED ) engine=memory;

对于mysql> = 5.6,您可以在配置中设置default_tmp_storage_engine=MEMORY以使其成为永久选项。

由于您已经拥有良好的索引,因此如果分析其余查询的优化是有意义的,则取决于临时表中的数据量。

答案 1 :(得分:0)

请勿使用IN ( SELECT ... ),而是使用JOIN。然后将TempTable作为子查询使用JOIN ( SELECT ... ),将其作为TempTable的正文。

请勿使用'commajoin',请使用显式JOIN ... ON

拥有INDEX(objectId, date)INDEX(user, id)

MEMORY表用于临时表是危险的,因为您无法预测所需的max_heap_table_size值。设置太大可能会窃取RAM,从而减慢一切。