代码之家  ›  专栏  ›  技术社区  ›  Tesserex

哪一个更快,水平计数还是垂直计数?

  •  1
  • Tesserex  · 技术社区  · 14 年前

    我需要从许多行中获取摘要数据。摘要字段是对不同字段中每个值有多少个条目的计数。例如,一个包含人的年龄、城市、工作等的表,摘要数据包括每个工作的“CountManager”、“CountcodeMonkey”等字段,然后是城市的“CountChicago”、“CountNewYork”等字段。

    我知道获得一切的一个简单方法是:

    select count(*) from table
        group by age, city, job
    

    但这是垂直计数-对于我需要的每个值都有不同的行。我需要字段,而不是具有计数的行,因为我有其他字段要分组,例如状态。所以我希望我的结果是这样的:

    | State | countManager | countMonkey |
    |  IL   |      3       |     25      |
    |  NY   |      5       |     40      |
    

    我正在寻找两种方法来做到这一点。我们已经实现了一个,执行需要20分钟。我想知道另一种方法是否更快。

    当前方式如下:

    create view managers as
        select state, count(*) as theCount from table
            where job = 'Manager'
            group by state;
    
    create view monkeys as
        select state, count(*) as theCount from table
            where job = 'Monkey'
            group by state;
    
    select managers.theCount as managers, monkeys.theCount as monkeys
        from managers left join monkeys
            on managers.state = monkeys.state;
    

    在实际情况中,还有大约20个视图,因此还有20个连接。

    我正在考虑以下水平计数方法:

    select state,
      sum(case when job='Manager' then 1 else 0 end) as managers,
      sum(case when job='Monkey' then 1 else 0 end) as monkeys
        from table
            group by state;
    

    这样就消除了连接。但我对“总和”陈述的表现一无所知。这会更快,大约相同,还是慢得多?对于每一个这样的计数字段,引擎是否必须多次遍历行?或者它是否足够智能,可以计算一次运行中的所有字段,检查每个值并增加适当的和?

    我可能会花一天的时间编写一个脚本来生成大量的垃圾数据来测试这一点,但是我仍然想知道DB引擎是如何工作的,我在网上找不到它。

    2 回复  |  直到 14 年前
        1
  •  3
  •   Nathan Wheeler    14 年前

    完全取决于引擎和您希望如何查看数据,但是您的第二个选项肯定会更快完成。

    即使是第一个查询,20分钟也是荒谬的,除非你有几十亿行。在这种情况下,您应该每月/每周查看归档数据,并将预编译的聚合数据放在一个表中,在该表中您可以根据需要进行切片和切块。

        2
  •  1
  •   lcardosobr    14 年前

    如果您的事务与其他事务之间没有并发性,“sum case”是一个不错的选择。聚合函数为 AVG , SUM , GROUP BY ,降低性能。与两件事保持联系:“分而治之”和“数字数据比文本数据更快”。

    创建一个数据仓库(一个表,一个数据库),以避免并发并提高处理能力。

    CPU是神奇的计算器:转换你的分类数据( "NY" , "LA" , "Man" , "Woman" )按数字数据( 1 , 2 , 61 , 62 )改善你的开采。

    理清你对数据库供应商或平台选择,但关系代数的想法。