- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我的查询看起来像这样:
select cat1, cat3, cat4
sum(case when cat2='x' then val end) as sumValForX,
sum(case when cat2='y' then val end) as sumValForY
from your_table WHERE date between somedate and someotherdate AND mainname=somename
group by cat1, cat3, cat4
基本上,这将我的表分组为 cat1,3,4;并分别显示当 cat2='x' 和 cat2='y' 时结果组的累积总数。
我正在处理一个非常大的表(比如 500 万条记录),所以这当然需要很多时间。这是可行的,但我只是想问问这里的一些 MySQL 专家,我可以对我的表进行什么样的优化,以加快速度。
这里使用的最佳技术是什么
分组速度更快
WHERE 更快(索引?分区?)
速度更快的情况(我认为这是主要的减速)。
关于数据的一些见解:
在大约 500 万条记录中,
mainname
是重复值最多的列。所以 5 种类型的 mainname
可能需要 100 万。
在这 100 万个日期中,我在大约 90 个日期范围内执行 BETWEEN 语句。
此外,在每 100 万个中,最多有 4-5 个不同的 cat2
。因此可能还有“x”、“y”或者“z”、“z1”,但不会更多。我有与 cat2
的类型数量相对应的附加 sum(case when... 语句。
换句话来说,我需要每种类型 cat2
的分组总和。
非常感谢。
最佳答案
CASE
表达式不太可能导致太大的“减速”。您可以通过从 SELECT 列表中删除这些表达式来测试这一点。)
合适的覆盖索引可能是提高此查询性能的最佳选择。
根据我的经验,对于大型集合上的此类查询,GROUP BY
是最大的减慢速度。我知道,使用 InnoDB 和合适的覆盖索引,我有时能够消除“使用文件排序”操作(如 EXPLAIN 输出所示)。MySQL 可以使用具有适当前导列的索引来优化 GROUP BY 操作,而不是使用“使用文件排序”操作。 date
列上的范围谓词(在 WHERE 子句中)可能会出现问题,并会产生干扰。
我们需要运行EXPLAIN
来验证。
根据查询,我建议使用覆盖索引:
... ON your_table (mainname, cat1, cat3, cat4, date, cat2)
首先是mainname
列(由于WHERE
子句中的等式谓词,MySQL可以使用索引范围扫描)。
接下来是 GROUP BY
子句中的三列(以优化 GROUP BY 操作)。
后面是查询中引用的附加列(使其成为“覆盖”索引,无需引用基础表中的页面。)
我们希望在 EXPLAIN 输出中看到“使用索引”,而不是“使用临时”和“使用文件排序”。
(我在这里假设对 somedate
、someotherdate
和 somename
的引用是对语句中提供的文字值的引用,而不是列引用文献。)
如果返回的行数非常小(与表的大小相比),那么您可以尝试创建一个索引,以 maindate
作为前导列,后跟 date
列,然后是按任意顺序排列的其他列。使用该索引,MySQL 可以对date
列进行范围扫描,但随后需要执行“文件排序”操作来执行 GROUP BY。
如果返回行的顺序并不重要,您可以尝试添加ORDER BY NULL
。我没有看到任何性能提升,但文档表明优化是可能的(也许在最近或 future 的版本中?)
对于一个大集合,我的直觉是优化 GROUP BY
。
如果我无法获得良好的执行计划(date
列上的谓词可能是个问题),我会探索重写语句以将该谓词重新定位到的选项CASE 表达式:
SUM(CASE WHEN t.date BETWEEN 'foo' AND 'bar' AND t.cat2 = 'x' THEN t.val END)
请注意,这可能会通过返回未出现在指定日期范围内的 (cat1,cat3,cat4)
值来更改结果集。如果这是一个问题,我可能会想出一个 HAVING
子句来消除那些“额外”的行。
如果可移植性不是问题,我可能会选择等效的 MySQL IF()
表达式
SUM(IF(t.date BETWEEN 'foo' AND 'bar' AND t.cat2 = 'x', t.val, NULL))
(但这不太可能对性能产生任何改变。)
关于mysql - 使用 CASE WHEN 优化查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25169538/
我经常在 ATS 中看到使用 case、case+ 或 case- 形成的 case 表达式。有什么区别? 最佳答案 如果表达式不详尽,使用 case 会发出警告,case+ 会产生错误,而 case
我有一个导入时全部大写的表,我想将其转换为正确的大小写。你们用什么脚本来完成这个? 最佳答案 这个函数: “正确大小写”由空格分隔的所有“大写”单词 保留“小写单词” 即使对于非英语字母也能正常工作
#include int main() { switch(2) { case 1: if(1)
我已经四处寻找了一段时间,如果我使用的术语不当,请原谅我... 代码的目标是在输入为 0 时更新 Aout1 和 Aout0,输出对应于 7 段显示,但出现以下错误: “错误 (10170):Four
我正在尝试按照 PostgreSQL 手册中的说明进行操作。 PostgreSQL: Documentation: 9.1: Control Structures 我的 PostgreSQL 服务器是
我有一个状态机,其中有几个非常相似的状态。我可以为每个状态编写它,如下例所示: module CHECK_FSM ( GO, DONE, CLK, RESETN ); input GO;
如何使用或创建案例? 就像是: string str; case (str) "abc" || "dfg": begin //some code end "yfg":
这个问题已经有答案了: Are double and single quotes interchangeable in JavaScript? (23 个回答) 已关闭 9 年前。 我正在学习Java
汽车 Make | Model | Year | Color Honda | Accord | 12 | Red Lexus | IS | 14 |
如何使用当前 case 语句的值跳转到 switch-case 条件下的另一个 case 语句? 是否可以使用 switch case 来实现这种事情,或者是否有其他实现方式? 有可能实现吗?如果没有
我理解下面的代码。 var day = 2; switch (day) { case 1: document.write("Monday"); break;
这是有效的。 object FilesToDFDS { case class Student(id: Int, name: String, dept:String) def main(
我对 VHDL 还是个新手。我需要在 CASE 语句中为多个信号赋值,如下所示: CASE input24 IS WHEN "00" THEN output0
我有这个 case 语句,它给出了一个错误“变量 constant1 未使用”。它似乎忽略了变量并返回了第一行,因此变量显然没有范围。如果我用数字 1 替换常量,那么它就可以工作。在 Elixir 中
在 MySQL 中,是否可以在 SELECT 子句中有两个 CASE 语句,其中第二个 CASE 语句依赖于第一个 CASE 语句? 例如,考虑以下查询: SELECT CASE WHEN `user
我正在尝试一个挑战,我需要获得一个随机数,并在没有重复的情况下打印数字内的数字总和:例如,123 将打印 6 ( 1 + 2 + 3 ),而 32111 将做同样的事情(因为我们没有在我们的总和中添加
当有人试图更新当前未存储在我的散列中的值时,我想立即返回 when 'add' 而无需重新启动整个 case声明,因为我已经知道他们想要添加并且不想再次提示他们。 有没有一种方法可以在不重新启动整个案
老 C 程序员可以在 Swift 方面得到一些帮助。 我不太了解 if-case 语法。例如: if case 20...30 = age { print ("in range.") } cas
老 C 程序员可以在 Swift 方面得到一些帮助。 我不太了解 if-case 语法。例如: if case 20...30 = age { print ("in range.") } cas
我有一个 ArrayList,其中包含以下字符串:[name, age, gender, salary] . 有没有办法可以将 ArrayList 中的值用作 case 表达式? 显而易见的答案是否定
我是一名优秀的程序员,十分优秀!