使用嵌套选择语句优化 MySQL 查询?

Posted

技术标签:

【中文标题】使用嵌套选择语句优化 MySQL 查询?【英文标题】:Optimizing MySQL query with nested select statements? 【发布时间】:2013-09-04 22:37:55 【问题描述】:

我对 mysql 数据库具有只读访问权限,我需要循环以下查询大约 9000 次,每次使用不同的 $content_path_id。我从一个 PERL 脚本中调用它,该脚本从文件中提取“$content_path_id”。

SELECT an.uuid FROM alf_node an WHERE an.id IN 
    (SELECT anp.node_id FROM alf_node_properties anp WHERE anp.long_value IN 
        (SELECT acd.id FROM alf_content_data acd WHERE acd.content_url_id = $content_path_id));

以这种方式编写,每次查询都需要 永远 (每次大约需要 1 分钟)。如果我不需要的话,我真的宁愿不要等待 9000 多分钟才能完成。有没有办法加快这个查询?也许通过加入?我目前的 SQL 技能生疏得令人尴尬……

【问题讨论】:

为什么不在一个表中包含所有$content_path_id,用alf_content_data 连接该表(在content_url_id 上),然后用alf_node_properties 连接结果,然后用@ 连接结果987654327@? EXISTS 可能比IN 更快。见***.com/questions/14190788/… 谢谢尼赞。不幸的是,我只有对数据库的只读访问权限,所以我无法添加表。 【参考方案1】:

试试这个 Laurence 解决方案的扩展,它用一个额外的 JOIN 替换长长的 OR 列表:

Select
    an.uuid 
From alf_node an
Join alf_node_properties anp
    On an.id = anp.node_id 
Join alf_content_data acd 
    On anp.long_value = acd.id 
Join (
    select "id1" as content_path_id union all
    select "id2" as content_path_id union all
    /* you get the idea */
    select "idN" as content_path_id 
) criteria   
    On acd.content_url_id = criteria.content_path_id

我已经使用了上面的 SQL Server 语法,但你应该可以很容易地翻译它。

【讨论】:

【参考方案2】:

这是一个使用连接的等效查询。这取决于表上定义的索引如何执行。

如果您的 Perl 接口具有预准备语句的概念,您可以通过准备一次并执行 9000 个不同的绑定来节省一些时间。

您还可以通过使用大的 acd.content_url_id In ($content_path_id1, $content_path_id2, ...) 子句构建一个查询来节省时间

Select
    an.uuid 
From
    alf_node an
        Inner Join
    alf_node_properties anp
        On an.id = anp.node_id 
        Inner Join
    alf_content_data acd 
        On anp.long_value = acd.id 
Where
    acd.content_url_id = $content_path_id

【讨论】:

谢谢 Laurence:这似乎有点,但不是很多,更快。我想知道是否可以通过将所有 9000 个查询作为“OR”放在“where”行中并将其作为一个巨型查询执行来使其更快。这会有帮助吗? 如果alf_content_data (content_url_id, acd.id) 上没有索引,那么它几乎肯定会使其更快。我对 ($content_path_id1, ..) 等中的 `acd.content_url_id 的建议与此等价。 抱歉——我没有注意到您原始答案中的“acd.content_url_id In”位。这确实有助于进行较小的测试,因此现在正在运行全尺寸测试。谢谢! 整个更长的查询在不到 2 分钟的时间内完成,所以我可以确认“acd.content_url_id IN”位实际上大大加快了速度。再次感谢劳伦斯!

以上是关于使用嵌套选择语句优化 MySQL 查询?的主要内容,如果未能解决你的问题,请参考以下文章

mysql explain的使用(优化查询)

mysql性能优化2

mysql查询优化策略

MySQL使用explains优化慢查询

MySQL语句优化技巧?

mysql优化--explain