我在MySQL上运行了一个drupal 7站点。网站上的某些页面加载速度极慢。
我调查了加载时间,并确定了罪魁祸首查询,该查询定期在某些页面上执行10秒。在一个案例中它甚至需要70秒!
查询来自“视图”,该视图根据网站分类法从网站的其他位置生成相关内容的简短列表。
这是一个慢页面的示例(带参数):
SELECT node.nid AS nid, node.title AS node_title, node.created AS node_created, 'podcasts:panel_pane_3' AS view_name, RAND() AS random_field
FROM node node
LEFT JOIN (SELECT td.*, tn.nid AS nid
FROM taxonomy_term_data td
LEFT JOIN taxonomy_vocabulary tv ON td.vid = tv.vid
LEFT JOIN taxonomy_index tn ON tn.tid = td.tid
WHERE (tv.machine_name IN ('listen')) ) taxonomy_term_data_node
ON node.nid = taxonomy_term_data_node.nid
LEFT JOIN taxonomy_index taxonomy_index ON node.nid = taxonomy_index.nid
WHERE (( (taxonomy_index.tid IN ('472', '350', '742', '681', '3907', '1541', '411', '636', '990', '7757', '680', '743', '11479', '8106', '566', '2230', '11480', '766'))
AND (node.nid != '191314' OR node.nid IS NULL) )
AND(( (node.status = '1')
AND (node.type IN ('article', 'experiment', 'interview', 'podcast', 'question')) )))
ORDER BY random_field ASC, node_created DESC
LIMIT 5 OFFSET 0
从最初的研究中我认为这是添加索引的情况,但相关表的列似乎有现有的索引条目。
因此我不确定如何继续,如果有人可以帮助我,我会非常重视某些指导吗?
答案 0 :(得分:0)
优化此查询的建议很少:
td.*
中的所有列吗?在大多数情况下,这意味着过多的信息通过网络传递给应用程序。random_field ASC, node_created DESC
。按不同的顺序排序将阻止索引使用,这将减慢搜索速度。您是否认为同时制作ASC或DESC两者都有意义?taxonomy_index.tid
是数字,'node.nid'和'node.status'也是。在这种情况下,将它们与常量进行比较时,不要在常量周围添加引号,因为它会导致不必要的强制转换,这可能会阻止索引的使用。例如,将node.status = '1'
转为node.status = 1
。taxonomy_term_data_node
)。 5.6,甚至可能是MySQL 5.7,MySQL最有可能无法正确索引该子查询。因此,我建议将该子查询提取到临时表,索引它并从外部查询加入它。请参阅下面的转换。因此,要应用大多数更改(不需要您做出决定的更改,例如上面的第1部分和第2部分),请执行以下步骤:
首先,通过添加以下索引来索引主查询:
ALTER TABLE
`node`
ADD
INDEX `node_idx_status_nid_title_created` (`status`, `nid`, `title`, `created`);
ALTER TABLE
`taxonomy_index`
ADD
INDEX `taxonomy_index_idx_nid` (`nid`);
ALTER TABLE
`taxonomy_index`
ADD
INDEX `taxonomy_index_idx_tid_nid` (`tid`, `nid`);
ALTER TABLE
`taxonomy_term_data`
ADD
INDEX `taxonomy_term_data_idx_vid_tid` (`vid`, `tid`);
ALTER TABLE
`taxonomy_vocabulary`
ADD
INDEX `taxonomy_vocabulary_idx_vid` (`vid`);
首先,创建临时表:
CREATE TEMPORARY TABLE IF NOT EXISTS temp1 AS SELECT
taxonomy_term_data.*,
tn.nid AS nid
FROM
taxonomy_term_data td
LEFT JOIN
taxonomy_vocabulary tv
ON td.vid = tv.vid
LEFT JOIN
taxonomy_index tn
ON tn.tid = td.tid
WHERE
(
tv.machine_name IN (
'listen'
)
);
现在索引子查询:
ALTER TABLE temp1
ADD INDEX temp1_idx_nid
(nid
);
外部查询将加入它:
SELECT
node.nid AS nid,
node.title AS node_title,
node.created AS node_created,
'podcasts:panel_pane_3' AS view_name,
RAND() AS random_field
FROM
node node
LEFT JOIN
temp1 taxonomy_term_data_node
ON node.nid = taxonomy_term_data_node.nid
LEFT JOIN
taxonomy_index taxonomy_index
ON node.nid = taxonomy_index.nid
WHERE
(
(
(
taxonomy_index.tid IN (
'472', '350', '742', '681', '3907', '1541', '411', '636', '990', '7757', '680', '743', '11479', '8106', '566', '2230', '11480', '766'
)
)
AND (
node.nid != '191314'
OR node.nid IS NULL
)
)
AND (
(
(
node.status = '1'
)
AND (
node.type IN (
'article', 'experiment', 'interview', 'podcast', 'question'
)
)
)
)
)
ORDER BY
random_field ASC,
node_created DESC LIMIT 5
答案 1 :(得分:0)
感谢上面的指导,大家。但是,我在剑桥大学的Andy Batey的帮助下解决了这个问题。
线索是比较上面的查询在MySQL v5.5上运行时生成的EXPLAIN语句(非常快的结果)与v5.7(非常慢的结果);他们在两个平台上的查询处理方式完全不同。
关键是将此添加到my.cnf:
optimizer_switch='derived_merge=off'
现在,本机查询的执行时间为50毫秒或更短,而之前为12秒或更长时间。
我希望这可以帮助遇到此升级问题的其他任何人。