哪个更快,水平或垂直计数?

时间:2010-09-17 21:46:53

标签: sql database postgresql query-optimization

我需要从许多行中获取摘要数据。摘要字段是不同字段的每个值的条目数。例如,一个包含人的年龄,城市,工作等的表格,摘要数据将包括每个作业的“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 个答案:

答案 0 :(得分:3)

完全取决于引擎以及您希望如何查看数据,但您的第二个选项应该更快地完成。

即使你的第一个查询20分钟也是荒谬的,除非你有数十亿行。在这种情况下,您应该每月/每周查看归档数据,并在表格中预编译汇总数据,您可以在其中切片和切块以适应。

答案 1 :(得分:1)

如果您的交易与其他交易不存在并发,“总和案例”是一个不错的选择。聚合函数AVGSUMGROUP BY会降低性能。与两件事保持联系:“分而治之”和“数字数据比文本数据更快”。

创建一个数据仓库(单个表,一个数据库)以避免并发并加速处理。

CPU是非常棒的计算器:通过数字数据("NY",{{1}转换您的分类数据("LA""Man""Woman"1) }},261)并改善您的挖掘。

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