这很奇怪。我正在尝试在MySQL中使用Views(对于具有Sybase和SQL Server的更多经验,我是MySQL的新手)。无论如何,这个新项目我们都在使用MySQL,因为它似乎具有良好的性能。然而,为了简化Web前端的查询,我们决定创建一些视图,一切都运行良好,但它们需要永远运行。
视图非常简单,只需选择语句(这些表中确实有几百万行)。比如说这个查询:
SELECT CAST(classifier_results.msgDate as DATE) AS mdate
,classifier_results.objClass AS objClass
,COUNT(classifier_results.objClass) AS obj
,classifier_results.subjClass AS subjClass
,COUNT(classifier_results.subjClass) AS subj
FROM classifier_results
WHERE (classifier_results.msgDate >= (curdate() - 20))
GROUP BY
CAST(classifier_results.msgDate as DATE)
,classifier_results.objClass
,classifier_results.subjClass
ORDER BY classifier_results.msgDate DESC
以普通方式运行时,大约需要1.5秒才能返回结果。
然而,当这个查询被放入视图中时(即) - 即
CREATE VIEW V1a_sentiment_AI_current AS
SELECT CAST(classifier_results.msgDate as DATE) AS mdate
,classifier_results.objClass AS objClass
,COUNT(classifier_results.objClass) AS obj
,classifier_results.subjClass AS subjClass
,COUNT(classifier_results.subjClass) AS subj
FROM classifier_results
WHERE (classifier_results.msgDate >= (curdate() - 20))
GROUP BY
CAST(classifier_results.msgDate as DATE)
,classifier_results.objClass
,classifier_results.subjClass
ORDER BY classifier_results.msgDate DESC
查询大约需要10倍(22-30秒)。所以我想也许有一些优化或查询缓存不能与Views一起使用,或者我们在MySQL配置中错过了一些设置。但有没有办法加快这个视图,所以它只是这个查询的一个不错的占位符?
对两个查询运行EXPLAIN: 正常选择给出:
1,SIMPLE,classifier_results,ALL,idx_date ,,,, 594845,使用where;使用临时;使用filesort
视图选择给出:
1,PRIMARY ,, ALL ,,,,, 100,
2,DERIVED,classifier_results,ALL,idx_date ,,,, 594845,使用where;使用临时;使用filesort
答案 0 :(得分:1)
这是一个非常常见的问题。编写DRY,可重用的SQL可能非常困难。我找到了一种解决方法。
首先,正如其他人所指出的,你可以而且应该使用VIEWs尽可能使用set ALGORITHM = MERGE来执行此操作,以便使用它们的任何查询在合并的SQL语句的where子句上进行优化,而不是使VIEW评估整个视图,这可能是灾难性的大。
在这种情况下,由于组/计数方面您无法使用MERGE,因此您可能希望尝试使用创建临时会话表的存储过程作为变通方法。
这种技术允许您编写可重用的查询,这些查询可以从中间件/框架代码访问,并从其他存储过程中调用,因此您可以保持代码包含,可维护和可重用。
即。如果您事先知道将在某些条件下过滤查询,请将它们放在存储过程中。 (对数据集进行后置过滤或组合可能更有效 - 这取决于您如何使用数据以及需要哪些常用集合。)
CREATE PROCEDURE sp_create_tmp_V1a_sentiment_AI_current(parm1, parm2 etc)
BEGIN
drop temporary table if exists tmp_V1a_sentiment_AI_current;
create temporary table tmp_V1a_sentiment_AI_current
as
SELECT CAST(classifier_results.msgDate as DATE) AS mdate
,classifier_results.objClass AS objClass
,COUNT(classifier_results.objClass) AS obj
,classifier_results.subjClass AS subjClass
,COUNT(classifier_results.subjClass) AS subj
FROM classifier_results
WHERE (classifier_results.msgDate >= (curdate() - 20))
-- and/or other filters on parm1, parm2 passed in
GROUP BY
CAST(classifier_results.msgDate as DATE)
,classifier_results.objClass
,classifier_results.subjClass
ORDER BY classifier_results.msgDate DESC;
END;
现在,只要您需要处理这些数据,就可以调用该过程,然后选择结果(可能还有其他where子句参数),或者在任何其他查询中加入它。
该表是一个会话临时表,因此它将持续超出对该过程的调用。调用代码可以在数据完成后丢弃,也可以在会话进行或后续调用sproc时自动进行。
希望有所帮助。
答案 1 :(得分:0)
尝试使用以下方法重新创建视图:
CREATE ALGORITHM = MERGE VIEW `V1a_sentiment_AI_current` AS
SELECT CAST(classifier_results.msgDate as DATE) AS mdate
,classifier_results.objClass AS objClass
,COUNT(classifier_results.objClass) AS obj
,classifier_results.subjClass AS subjClass
,COUNT(classifier_results.subjClass) AS subj
FROM classifier_results
WHERE (classifier_results.msgDate >= (curdate() - 20))
GROUP BY
CAST(classifier_results.msgDate as DATE)
,classifier_results.objClass
,classifier_results.subjClass
ORDER BY classifier_results.msgDate DESC
可以找到有关MySQL视图处理算法的更多信息here。
答案 2 :(得分:0)
此处不能使用MERGE;在这些情况下,它可能有助于指定TEMPTABLE以保存引擎不必在它们之间做出决定。一旦我决定使用哪种算法,我会查看EXPLAIN计划并尝试添加索引提示或找到缺失的索引。