如何优化此SQL查询

时间:2011-02-20 13:48:30

标签: sql mysql performance

以下是一个耗时太长的查询;它有一些位,但它是一个非常简单的查询。我想问一下,有谁可以看到它的哪一部分可能导致性能瓶颈?万分感谢。

SELECT DISTINCT node.nid AS nid
  , node_data_field_company_logo.field_company_logo_fid
    AS node_data_field_company_logo_field_company_logo_fid
  , node_data_field_company_logo.field_company_logo_list
    AS node_data_field_company_logo_field_company_logo_list
  , node_data_field_company_logo.field_company_logo_data
    AS node_data_field_company_logo_field_company_logo_data
  , node.type AS node_type, node.vid AS node_vid
  , node_data_field_company_logo.field_job_details_title_value
    AS node_data_field_company_logo_field_job_details_title_value
  , RAND() AS _random
FROM node node
  LEFT JOIN term_node term_node
    ON node.vid = term_node.vid
  LEFT JOIN term_data term_data
    ON term_node.tid = term_data.tid
  LEFT JOIN content_type_profile_job_post node_data_field_company_logo
    ON node.vid = node_data_field_company_logo.vid
WHERE (node.type in ('profile_job_post'))
  AND (node.status <> 0)
  AND ((term_data.name) = (''))
ORDER BY _random ASC

2 个答案:

答案 0 :(得分:0)

这很简单。以下是一些可以提高性能的显而易见的事情:

  1. 你为什么要按_random排序?那会让你慢下来。
  2. 你为什么需要DISTINCT?做DISTINCT有一个隐含的GROUP BY,它会降低你的速度。
  3. 如果将(node.type in ('profile_job_post'))写为node.type = 'profile_job_post',则优化程序更有可能注意到它对优化很有用。
  4. 除此之外,它看起来很合理。但是理智检查。你有所有相关指数吗?你的桌子有多大?你的结果集有多大?查询有多慢?你能给我们一个EXPLAIN计划吗?

    如果没有这些信息,我们只需要猜测是否存在真正的问题,或者您的期望是否不合理。

答案 1 :(得分:0)

首先,让我们摆脱所有那些无用的别名。并注意要求表结构,索引和EXPLAIN输出的注释。

SELECT DISTINCT node.nid AS nid
  , node_data_field_company_logo.field_company_logo_fid
  , node_data_field_company_logo.field_company_logo_list
  , node_data_field_company_logo.field_company_logo_data
  , node.type, node.vid
  , node_data_field_company_logo.field_job_details_title_value
  , RAND() AS _random
FROM node 
  LEFT JOIN term_node 
    ON node.vid = term_node.vid
  LEFT JOIN term_data 
    ON term_node.tid = term_data.tid
  LEFT JOIN content_type_profile_job_post 
    ON node.vid = node_data_field_company_logo.vid
WHERE (node.type in ('profile_job_post'))
  AND (node.status <> 0)
  AND ((term_data.name) = (''))
ORDER BY _random ASC

简单的事情:您通常会受益于JOIN子句或WHERE子句中使用的任何列的索引。

node.status
node.type
node.vid
node_data_field_company_logo.vid
term_data.name
term_data.tid
term_node.vid

但它取决于每个列中不同值的数量。例如,如果node.status只能有两个值0和1,那么索引可能无法帮助它。 (这是发布表结构的一个原因很重要。)

重新审视简单的事情:你将为随机订单支付沉重的代价。

稍微复杂一点:您可能会从节点表上创建视图中受益。视图应该只选择您实际需要的列和行。然后在该视图上加入,而不是直接使用节点表。