我有两张桌子:
module_339 (id,name,description,etc)
module_339_schedule(id,itemid,datestart,dateend,timestart,timeend,days,recurrent)
module_339_schedule.itemid指向module_339
拳头桌举行会议
第二个保留会议的时间表
module_339有3个项目
module_339_schedule有4000多个项目 - 几乎在3个会议之间分配
我有一个存储功能 - " getNextDate_module_339" - 这将计算"下一个日期"对于指定的会议,为了能够显示它,并根据它进行排序 - 如果用户想要的话。此存储过程将只获取指定会议的所有计划条目并循环显示它们,比较日期和时间。所以它会从module_339_schedule做一个简单的读取,然后遍历这些项目并比较日期和时间。
问题:此查询非常慢:
SELECT
distinct(module_339.id)
,min( getNextDate_module_339(module_339.id,1,false)) AS ND
FROM
module_339
LEFT JOIN module_339_schedule on module_339.id=module_339_schedule.itemid /* standard schedule adding */
WHERE 1=1 AND module_339.is_system_preview<=0
group by
module_339.id
order by
module_339.id asc
如果我删除了函数调用或LEFT JOIN,它再次快速。 我在这做错了什么?似乎是某种&#34;碰撞&#34;在函数调用和左连接之间。
答案 0 :(得分:1)
我认为group by
部分可以从此查询中删除,因此您也可以删除min
功能。此外,WHERE 1=1 AND...
没有多大意义,所以我也改变了这一点。
试试这个:
SELECT DISTINCT module_339.id
,getNextDate_module_339(module_339.id,1,false) AS ND
FROM module_339
LEFT JOIN module_339_schedule ON module_339.id=module_339_schedule.itemid /* standard schedule adding */
WHERE module_339.is_system_preview<=0
ORDER BY module_339.id
注意,这可能不会对性能产生太大影响
我认为性能最差的部分可能是getNextDate_module_339
函数
如果你能找到一种方法来获得它的功能而不使用函数作为子查询,你的sql语句可能会比现在运行得更快,无论有没有左连接。
如果您需要帮助,请编辑您的问题以包含该功能,并希望我(或其他人)可以帮助您。
答案 1 :(得分:0)
从MySQL参考手册:
提高SELECT操作性能的最佳方法是在查询中测试的一个或多个列上创建索引。索引条目的作用类似于表行的指针,允许查询快速确定哪些行与WHERE子句中的条件匹配,并检索这些行的其他列值。可以索引所有MySQL数据类型。
虽然为查询中使用的每个可能列创建索引很有吸引力,但不必要的索引会浪费空间并浪费时间让MySQL确定要使用的索引。索引还会增加插入,更新和删除的成本,因为必须更新每个索引。您必须找到适当的平衡,以使用最佳索引集实现快速查询。
作为第一步,我建议检查已连接的列是否已编入索引。由于主键始终默认为索引,因此我们可以假设module_339已在id列上编入索引,因此首先验证module_339_schedule是否已在itemid列上编入索引。您可以使用以下方法检查MySQL中该表的索引:
SHOW INDEX FROM module_339_schedule;
如果表中没有该列的索引,您可以使用以下命令添加:
CREATE INDEX itemid_index ON module_339_schedule (itemid);
这应该加快查询的连接组件。
由于您的查询还引用了module_339.is_system_preview,您还可以考虑使用以下方法向该列添加索引:
CREATE INDEX is_system_preview_index ON module_339 (is_system_preview);
您也可以优化存储过程,但未将其包含在您的问题中。