[英]SQL Query optimization with UNION ALL
我遵循了此链接中的说明
似乎并没有太大改善(仅改善了0.09秒)。 还不够,我的目标是对其进行更多优化。
桌子
state: id,title,abbr
regions: id,title
regions_suburbs: region_id,suburb_id
suburbs: id,state_id,region_id,postcode
properties: id,title
我试图在proprety.title,郊区.title,state.abbr,state.title和郊区.postcode中找到任何关键字。
查询如下
[Perivous]显示第0-4行(共5行,查询耗时4.7122秒)
SELECT * FROM (SELECT CASE WHEN p.id IS NOT NULL THEN CONCAT('project_id|',p.id) WHEN s.id IS NOT NULL THEN CONCAT('suburb_id|',s.id) ELSE '0' END AS id,s.title As SuburbName,s.postcode,st.abbr,CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END) AS SearchTerm FROM properties p LEFT OUTER JOIN suburbs s ON p.suburb_id=s.id LEFT JOIN regions_suburbs rs ON rs.suburb_id=s.id LEFT JOIN regions r ON rs.region_id=r.id LEFT JOIN state st ON st.id=s.state_id UNION ALL SELECT CASE WHEN p.id IS NOT NULL THEN CONCAT('project_id|',p.id) WHEN s.id IS NOT NULL THEN CONCAT('suburb_id|',s.id) ELSE '0' END AS id,s.title As SuburbName,s.postcode,st.abbr,CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END) AS SearchTerm FROM properties p RIGHT OUTER JOIN suburbs s ON p.suburb_id=s.id LEFT JOIN regions_suburbs rs ON rs.suburb_id=s.id LEFT JOIN regions r ON rs.region_id=r.id LEFT JOIN state st ON st.id=s.state_id UNION ALL SELECT CONCAT('state_id|',id),'' As SuburbName,'' AS postcode,abbr,title AS SearchTerm FROM state) AS U WHERE 1 AND (SuburbName LIKE 'Newtown%' OR postcode='Newtown' OR LOWER(SearchTerm) LIKE LOWER('Newtown%') OR abbr LIKE 'Newtown%') ORDER BY SearchTerm ASC LIMIT 0,10
说明结果
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 16657 Using where; Using filesort
2 DERIVED p ALL NULL NULL NULL NULL 3
2 DERIVED s eq_ref PRIMARY PRIMARY 4 residential.p.suburb_id 1
2 DERIVED rs ALL NULL NULL NULL NULL 383
2 DERIVED r eq_ref PRIMARY PRIMARY 4 residential.rs.region_id 1 Using index
2 DERIVED st eq_ref PRIMARY PRIMARY 4 residential.s.state_id 1
3 UNION s ALL NULL NULL NULL NULL 16640
3 UNION p ALL NULL NULL NULL NULL 3
3 UNION rs ALL NULL NULL NULL NULL 383
3 UNION r eq_ref PRIMARY PRIMARY 4 residential.rs.region_id 1 Using index
3 UNION st eq_ref PRIMARY PRIMARY 4 residential.s.state_id 1
4 UNION state ALL NULL NULL NULL NULL 8
NULL UNION RESULT <union2,3,4> ALL NULL NULL NULL NULL NULL
[现在]显示第0-4行(共5行,查询耗时4.6246秒)
SELECT CASE WHEN p.id IS NOT NULL THEN CONCAT('project_id|',p.id) WHEN s.id IS NOT NULL THEN CONCAT('suburb_id|',s.id) ELSE '0' END AS id,s.title As SuburbName,s.postcode,st.abbr,CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END) AS SearchTerm FROM properties p LEFT OUTER JOIN suburbs s ON p.suburb_id=s.id LEFT JOIN regions_suburbs rs ON rs.suburb_id=s.id LEFT JOIN regions r ON rs.region_id=r.id LEFT JOIN state st ON st.id=s.state_id WHERE 1 AND (s.title LIKE 'Newtown%' OR postcode='Newtown' OR LOWER(CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END)) LIKE LOWER('Newtown%') OR st.abbr LIKE 'Newtown%') UNION ALL SELECT CASE WHEN p.id IS NOT NULL THEN CONCAT('project_id|',p.id) WHEN s.id IS NOT NULL THEN CONCAT('suburb_id|',s.id) ELSE '0' END AS id,s.title As SuburbName,s.postcode,st.abbr,CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END) AS SearchTerm FROM properties p RIGHT OUTER JOIN suburbs s ON p.suburb_id=s.id LEFT JOIN regions_suburbs rs ON rs.suburb_id=s.id LEFT JOIN regions r ON rs.region_id=r.id LEFT JOIN state st ON st.id=s.state_id WHERE 1 AND (s.title LIKE 'Newtown%' OR postcode='Newtown' OR LOWER(CONCAT(CASE WHEN p.propertyname IS NULL THEN '' ELSE CONCAT(p.propertyname,', ') END,CASE WHEN s.title IS NULL THEN'' ELSE CONCAT(UPPER(s.title), ' ') END,CASE WHEN st.abbr IS NULL THEN '' ELSE CONCAT(UPPER(st.abbr), ' ') END,CASE WHEN s.postcode IS NULL THEN '' ELSE CONCAT(s.postcode, '') END)) LIKE LOWER('Newtown%') OR st.abbr LIKE 'Newtown%') UNION ALL SELECT CONCAT('state_id|',id),'' As SuburbName,'' AS postcode,abbr,title AS SearchTerm FROM state WHERE 1 AND title LIKE 'Newtown%' ORDER BY SearchTerm ASC LIMIT 0,10
说明结果
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY p ALL NULL NULL NULL NULL 3
1 PRIMARY s eq_ref PRIMARY PRIMARY 4 residential.p.suburb_id 1
1 PRIMARY rs ALL NULL NULL NULL NULL 383
1 PRIMARY r eq_ref PRIMARY PRIMARY 4 residential.rs.region_id 1 Using index
1 PRIMARY st eq_ref PRIMARY PRIMARY 4 residential.s.state_id 1 Using where
2 UNION s ALL title_postcode NULL NULL NULL 16640
2 UNION p ALL NULL NULL NULL NULL 3
2 UNION rs ALL NULL NULL NULL NULL 383
2 UNION r eq_ref PRIMARY PRIMARY 4 residential.rs.region_id 1 Using index
2 UNION st eq_ref PRIMARY PRIMARY 4 residential.s.state_id 1 Using where
3 UNION state range title title 102 NULL 1 Using where
NULL UNION RESULT <union1,2,3> ALL NULL NULL NULL NULL NULL Using filesort
把它里面翻出来。 而不是计算您想要的所有内容,然后查看每个结果块中是否都包含“ Newtown%”,...
properties
(假设这是该数据集的焦点); 只获取属性的主键。 完成此操作后,如果您愿意在ORDER BY中使用SearchTerm
以外的其他功能,则可以提高性能。 我只建议properties.id
。 这样,您可以在第2步和第3步中执行ORDER BY,以减少逐步挖掘的数量。
(当您拥有UNION
时, OFFSET
会引起另一个问题;我们可以单独解决。)
谢谢大家的帮助。 我终于找到了使查询变慢的元凶。
我试图从SQL语句中一点一点地删除它,然后一遍又一遍地运行它。 最后,在删除以下两个LEFT JOIN部分之后,
LEFT JOIN regions_suburbs rs
ON rs.suburb_id = s.id
LEFT JOIN regions r
ON rs.region_id = r.id
它从
Showing rows 0 - 1 (2 total, Query took 4.8538 sec)
至
Showing rows 0 - 1 (2 total, Query took 0.2337 sec)
为此,我必须对数据库的设计进行一些更改。 最初,属性表仅存储郊区_id,因为如果我们知道郊区_id,便可以获取其region_id和state_id。 为了避免向后加入region_suburbs和region表,我现在存储state_id,region_id和郊区_id,而不是仅存储一个郊区_id。 在这种情况下,我们可以从查询中删除两个LEFT JOIN,并通过利用两个值得的额外列存储来极大地缩短查询响应时间。
编辑:在我选择的列上创建一些索引也极大地改善了响应时间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.