需要加快MySQL查询速度吗
我有一个查询,用于获取各种输入以计算资产排名。为了获得基于用户输入计算资产等级的各种值,我对单个表使用了多个子查询。但这花费了太多的时间。有人能帮我临时提出这个问题吗需要加快MySQL查询速度吗,mysql,Mysql,我有一个查询,用于获取各种输入以计算资产排名。为了获得基于用户输入计算资产等级的各种值,我对单个表使用了多个子查询。但这花费了太多的时间。有人能帮我临时提出这个问题吗 SELECT AssetId, AssetName, Isin, (SELECT DClose FROM eod_data WHERE Isin=a.Isin AND DDate >= now()-interval 12 MONTH ORDER BY DDate
SELECT AssetId,
AssetName,
Isin,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 12 MONTH
ORDER BY DDate ASC LIMIT 1) AS rafval,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 12 MONTH
ORDER BY DDate DESC LIMIT 1) AS ralval,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 3 MONTH
ORDER BY DDate ASC LIMIT 1) AS rbfval,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 3 MONTH
ORDER BY DDate DESC LIMIT 1) AS rblval,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 20 DAY
ORDER BY DDate ASC LIMIT 1) AS rcfval,
(SELECT DClose
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 20 DAY
ORDER BY DDate DESC LIMIT 1) AS rclval,
(SELECT STD(DClose)
FROM eod_data
WHERE Isin=a.Isin
AND DDate >= now()-interval 20 DAY
ORDER BY DDate DESC LIMIT 1) AS vstd
FROM assets a
INNER JOIN assetclasses ac ON ac.AssetClassId=a.AssetClassId
INNER JOIN assetsubgroups asg ON asg.AssetSubGroupId=ac.AssetSubGroupId
WHERE asg.AssetGroupId=1
AND a.IsActive=1;
在上面的查询中,子查询中提到的所有间隔都是变量。它们来自用户输入。资产表包含1000个资产和eod_数据,将包含数百万条记录
我还为where子句中涉及的所有字段创建了索引
表结构
资产:资产名称、资产名称、Isin、IsActive
eod_数据:Isin、DClose、DDate
上面的查询大约需要11分钟
提前谢谢
请在此处找到示例数据库您可以尝试此查询吗。它只对所有列使用一个联接,但对于示例数据,最后一个字段每次都为null,查询也是如此
SELECT
AssetId
, AssetName
, a.Isin
, min(IF(DDate >= now()-interval 12 MONTH, DClose,null) ) AS rafval
, max(IF(DDate >= now()-interval 12 MONTH, DClose,null) ) AS ralval
, min(IF(DDate >= now()-interval 3 MONTH, DClose,null) ) AS rbfval
, max(IF(DDate >= now()-interval 3 MONTH, DClose,null) ) AS rblval
, min(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS rcfval
, max(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS rclval
, STD(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS vstd
FROM assets a
INNER JOIN assetclasses ac ON ac.AssetClassId=a.AssetClassId
INNER JOIN assetsubgroups asg ON asg.AssetSubGroupId=ac.AssetSubGroupId
LEFT JOIN eod_data ed ON ed.Isin = a.Isin
WHERE asg.AssetGroupId=1
AND a.IsActive=1
GROUP BY AssetId;
样本
MariaDB [test]> SELECT
-> AssetId
-> , AssetName
-> , a.Isin
-> , min(IF(DDate >= now()-interval 12 MONTH, DClose,null) ) AS rafval
-> , max(IF(DDate >= now()-interval 12 MONTH, DClose,null) ) AS ralval
-> , min(IF(DDate >= now()-interval 3 MONTH, DClose,null) ) AS rbfval
-> , max(IF(DDate >= now()-interval 3 MONTH, DClose,null) ) AS rblval
-> , min(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS rcfval
-> , max(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS rclval
-> , STD(IF(DDate >= now()-interval 20 DAY, DClose,null) ) AS vstd
-> FROM assets a
-> INNER JOIN assetclasses ac ON ac.AssetClassId=a.AssetClassId
-> INNER JOIN assetsubgroups asg ON asg.AssetSubGroupId=ac.AssetSubGroupId
-> LEFT JOIN eod_data ed ON ed.Isin = a.Isin
->
-> WHERE asg.AssetGroupId=1
-> AND a.IsActive=1
-> GROUP BY AssetId;
+---------+---------------------+---------+----------+----------+----------+----------+--------+--------+------+
| AssetId | AssetName | Isin | rafval | ralval | rbfval | rblval | rcfval | rclval | vstd |
+---------+---------------------+---------+----------+----------+----------+----------+--------+--------+------+
| 1 | AT ANDRITZ | ANDR_AT | 97.5700 | 97.5700 | 97.5700 | 97.5700 | NULL | NULL | NULL |
| 5 | AT BWT | BWTV_AT | 98.2000 | 98.2000 | 98.2000 | 98.2000 | NULL | NULL | NULL |
| 6 | AT ERSTE GROUP BANK | ERST_AT | 99.8000 | 99.8000 | 99.8000 | 99.8000 | NULL | NULL | NULL |
| 7 | AT EVN | EVNV_AT | 99.2600 | 99.2600 | 99.2600 | 99.2600 | NULL | NULL | NULL |
| 8 | AT FLUGHAFEN WIEN | VIEV_AT | 102.5200 | 102.5200 | 102.5200 | 102.5200 | NULL | NULL | NULL |
| 10 | AT IMMOFINANZ | IMFI_AT | 104.1600 | 104.1600 | 104.1600 | 104.1600 | NULL | NULL | NULL |
| 11 | AT LENZING | LENV_AT | 103.1300 | 103.1300 | 103.1300 | 103.1300 | NULL | NULL | NULL |
| 12 | AT MAYR MELNHOF | MMKV_AT | 104.3700 | 104.3700 | 104.3700 | 104.3700 | NULL | NULL | NULL |
| 13 | AT MEINL EUR LAND | MELV_AT | 103.0300 | 103.0300 | 103.0300 | 103.0300 | NULL | NULL | NULL |
| 14 | AT OMV | OMVV_AT | 102.7200 | 102.7200 | 102.7200 | 102.7200 | NULL | NULL | NULL |
| 15 | AT PALFINGER | PALF_AT | 101.2000 | 101.2000 | 101.2000 | 101.2000 | NULL | NULL | NULL |
| 17 | AT RHI AG | RHIV_AT | 98.7800 | 98.7800 | 98.7800 | 98.7800 | NULL | NULL | NULL |
| 18 | AT SCHOELLER-BLECK | SBOE_AT | 98.2100 | 98.2100 | 98.2100 | 98.2100 | NULL | NULL | NULL |
| 19 | AT SEMPERIT HDG | SMPV_AT | 98.4500 | 98.4500 | 98.4500 | 98.4500 | NULL | NULL | NULL |
| 20 | AT TELEKOM AUSTRIA | TELA_AT | 97.7400 | 97.7400 | 97.7400 | 97.7400 | NULL | NULL | NULL |
+---------+---------------------+---------+----------+----------+----------+----------+--------+--------+------+
15 rows in set (0.00 sec)
MariaDB [test]>
这是我的下一次尝试。我测试了一些不同的连接。这是最快的方式(快1400倍)。STD()列未在矩中实现。你能检查一下其他输出是否正确吗 …和最后的STD()(我希望)
你能再测试一下吗?有两个表的样本日期和创建日期吗?@Bernd Buffen感谢你的快速回复。现在我没有任何样本数据。我会创造一些东西。您需要它来检查数据格式还是测试查询?所以我将创建样本表好的,你可以把我放在上面,你可以把表和样本数据放在上面,再次感谢你的回复。实际上这里对于rafval,我需要该时间间隔的第一天值,对于ralval,我需要该时间间隔的最后一天值。。。类似的还有子查询。它不是最小值或最大值。关于样本数据,是的,它没有足够的数据进行所有计算。但是请不要介意,给我一些类似这样的想法,在查询中获取第一个和最后一个值来代替最小值和最大值。谢谢抱歉-min和max必须是正确的。如果你说min,你得到的是最低的日期,min中有一个if语句,它将通过范围中的一个日期。这不对吗?很抱歉,它没有返回该日期间隔中的第一个和最后一个值。它只返回最小值和最大值。还有一件事,我用真实数据检查了数据库的性能。与该查询匹配的总资产为1550个,需要584.754s。我添加了更多数据以满足所有条件。请检查这里Hi@Ravi,是否可以向我发送更多数据。执行时间总是低于1毫秒,我真的看不出某些索引是否工作得更好。你可以把它放在一些存储或直接发送到我的电子邮件配置文件。然后我会将结果发布到这里,创建了更多数据的数据库,正好复制了我现在的数据库。请从这里下载文件。非常感谢你的时间和努力。嗨@Bernd Buffen,真的很棒。出色的表现。但唯一的问题是它在给定的时间间隔内返回最小和最大DClose值。但我需要这个区间的第一个和最后一个值。以AssetId=1为例,在12个月结果集中,第一天的DClose值为42.6500。所以拉夫瓦尔应该是42.6500。但在我们的查询中,它返回38.6900。这是该资产在12个月内的最低价值。与最后一天相同的值为49.4400。但我们的查询返回49.7950作为ralval。这是此间隔中的最大值。请解决这个问题。感谢您的大力帮助。从eod_数据中选择STRAIGHT_JOIN AssetId、AssetName、a.Isin、ed.DDate、ed.DClose ed上的左连接资产a.Isin=a.Isin Internal JOIN AssetClass ac上的ac.AssetClassId=a.AssetClassId内部连接资产组asg上的ASETSUBGroupId=ac.AssetSubGroupId其中ed.DDate>=now()-间隔12个月,DDate ASC的asg.AssetGroupId=1和a.AssetId=1订单;只是为了检查我们结果中的第一个和最后一个值。嗨@Bernd Buffen运气好吗?@Ravi-是的,但我必须考虑一下最佳解决方案。今晚我可以做这件事。所有r[abc]lval值相同是否正确。每次都是范围的第一行和最后一行,但最后一行总是一样的?是的,你是对的。它是该范围的第一个和最后一个值。实际上,有4种不同类型的过滤器,带有日期和间隔。日期可能相同,也可能不同。对于默认视图,我们现在将显示默认间隔。但用户可以随时更改过滤器,并检查结果。那时我们必须得到所有的r[abc]lval。我希望你了解情况。非常感谢。
SELECT
a.AssetId
, a.AssetName
, a.Isin
, CAST(COALESCE(ed2.DClose,0) AS DECIMAL(20,4)) AS rafval
, CAST(COALESCE(ed3.DClose,0) AS DECIMAL(20,4)) AS ralval
, CAST(COALESCE(ed4.DClose,0) AS DECIMAL(20,4)) AS rbfval
, CAST(COALESCE(ed5.DClose,0) AS DECIMAL(20,4)) AS rblval
, CAST(COALESCE(ed6.DClose,0) AS DECIMAL(20,4)) AS rcfval
, CAST(COALESCE(ed7.DClose,0) AS DECIMAL(20,4)) AS rclval
, COALESCE(ed.vstd,0) AS vstd
FROM (
SELECT
ed.Isin
, MIN(IF( DDate >= now()-INTERVAL 12 MONTH, EodDataId, NULL)) AS id_rafval
, MAX(IF( DDate >= now()-INTERVAL 12 MONTH, EodDataId, NULL)) AS id_ralval
, MIN(IF( DDate >= now()-INTERVAL 3 MONTH, EodDataId, NULL)) AS id_rbfval
, MAX(IF( DDate >= now()-INTERVAL 3 MONTH, EodDataId, NULL)) AS id_rblval
, MIN(IF( DDate >= now()-INTERVAL 40 DAY , EodDataId, NULL)) AS id_rcfval
, MAX(IF( DDate >= now()-INTERVAL 40 DAY , EodDataId, NULL)) AS id_rclval
, std(IF( DDate >= now()-INTERVAL 40 DAY , NULL, DClose )) AS vstd
FROM eod_data ed
WHERE ed.DDate >= now()-INTERVAL 12 MONTH
GROUP BY ed.Isin
ORDER BY ed.EodDataId ASC
) ed
LEFT JOIN eod_data ed2 ON ed2.Isin = ed.Isin AND ed2.EodDataId = ed.id_rafval
LEFT JOIN eod_data ed3 ON ed3.Isin = ed.Isin AND ed3.EodDataId = ed.id_ralval
LEFT JOIN eod_data ed4 ON ed4.Isin = ed.Isin AND ed4.EodDataId = ed.id_rbfval
LEFT JOIN eod_data ed5 ON ed5.Isin = ed.Isin AND ed5.EodDataId = ed.id_rblval
LEFT JOIN eod_data ed6 ON ed6.Isin = ed.Isin AND ed6.EodDataId = ed.id_rcfval
LEFT JOIN eod_data ed7 ON ed7.Isin = ed.Isin AND ed7.EodDataId = ed.id_rclval
INNER JOIN assets a ON a.Isin = ed.Isin
INNER JOIN assetclasses ac ON ac.AssetClassId=a.AssetClassId
INNER JOIN assetsubgroups asg ON asg.AssetSubGroupId=ac.AssetSubGroupId
WHERE asg.AssetGroupId=1
AND a.IsActive=1
ORDER BY a.AssetId;
SELECT
a.AssetId
, a.AssetName
, a.Isin
, CAST(COALESCE(ed2.DClose,0) AS DECIMAL(20,4)) AS rafval
, CAST(COALESCE(ed3.DClose,0) AS DECIMAL(20,4)) AS ralval
, CAST(COALESCE(ed4.DClose,0) AS DECIMAL(20,4)) AS rbfval
, CAST(COALESCE(ed5.DClose,0) AS DECIMAL(20,4)) AS rblval
, CAST(COALESCE(ed6.DClose,0) AS DECIMAL(20,4)) AS rcfval
, CAST(COALESCE(ed7.DClose,0) AS DECIMAL(20,4)) AS rclval
FROM (
SELECT
ed.Isin
, MIN(IF( DDate >= now()-INTERVAL 12 MONTH, EodDataId, NULL)) AS id_rafval
, MAX(IF( DDate >= now()-INTERVAL 12 MONTH, EodDataId, NULL)) AS id_ralval
, MIN(IF( DDate >= now()-INTERVAL 3 MONTH, EodDataId, NULL)) AS id_rbfval
, MAX(IF( DDate >= now()-INTERVAL 3 MONTH, EodDataId, NULL)) AS id_rblval
, MIN(IF( DDate >= now()-INTERVAL 20 DAY , EodDataId, NULL)) AS id_rcfval
, MAX(IF( DDate >= now()-INTERVAL 20 DAY , EodDataId, NULL)) AS id_rclval
FROM eod_data ed
WHERE ed.DDate >= now()-INTERVAL 12 MONTH
GROUP BY ed.Isin
ORDER BY ed.DDate ASC
) ed
LEFT JOIN eod_data ed2 ON ed2.Isin = ed.Isin AND ed2.EodDataId = ed.id_rafval
LEFT JOIN eod_data ed3 ON ed3.Isin = ed.Isin AND ed3.EodDataId = ed.id_ralval
LEFT JOIN eod_data ed4 ON ed4.Isin = ed.Isin AND ed4.EodDataId = ed.id_rbfval
LEFT JOIN eod_data ed5 ON ed5.Isin = ed.Isin AND ed5.EodDataId = ed.id_rblval
LEFT JOIN eod_data ed6 ON ed6.Isin = ed.Isin AND ed6.EodDataId = ed.id_rcfval
LEFT JOIN eod_data ed7 ON ed7.Isin = ed.Isin AND ed7.EodDataId = ed.id_rclval
INNER JOIN assets a ON a.Isin = ed.Isin
INNER JOIN assetclasses ac ON ac.AssetClassId=a.AssetClassId
INNER JOIN assetsubgroups asg ON asg.AssetSubGroupId=ac.AssetSubGroupId
WHERE asg.AssetGroupId=1
AND a.IsActive=1
ORDER BY a.AssetId;