我正在寻找一种优化以下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后,这些表已经包含了我认为必要的索引。
答案 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,从而减慢一切。