【问题标题】:Performance of sql Count*sql 计数的性能*
【发布时间】:2009-11-05 09:47:17
【问题描述】:

asp.net 和 sql server,有用于选择行子集的 sql,我经常需要 count*

当然,我可以在每次往返中为这些 sql 中的每一个设置一个 select count(*),但很快它就会变得太慢。

-你如何让它变得非常快?

【问题讨论】:

    标签: sql sql-server database performance


    【解决方案1】:

    您是否遇到无法通过向表中添加另一个索引来解决的问题? COUNT(*) 操作的总行数通常为 O(log n),返回的行数通常为 O(n)。

    编辑:我的意思是(以防我误解了你的问题)

    鉴于此结构:

    CREATE TABLE emails (
        id INT,
        .... OTHER FIELDS
    )
    
    CREATE TABLE filters (
        filter_id int,
        filter_expression nvarchar(max) -- Or whatever...
    )
    

    创建表格

    CREATE TABLE email_filter_matches (
        filter int,
        email int,
        CONSTRAINT pk_email_filter_matches PRIMARY KEY(filter, email)
    )
    

    每次更新过滤器或收到新电子邮件时,都必须更新此表中的数据。

    然后,像这样的查询

    SELECT COUNT(*) FROM email_filter_matches WHERE filter = @filter_id
    

    对于过滤器匹配的总数应该是 O(log n),对于这个特定过滤器的匹配数应该是 O(n)。由于您的示例仅显示少量匹配项(这在电子邮件过滤器方面似乎很现实),这很可能没问题。

    如果您真的想这样做,当然可以在 email_filter_matches 表上创建一个触发器,以使过滤器表中的缓存值保持同步,但这可以在您遇到性能问题的那一天完成。在并发系统中正确处理这些事情并非易事。

    【讨论】:

    • 正如我所提到的,过滤器是由用户定义的,因此 where 子句是不可预测的,并且对于服务器来说可能是复杂且耗时的。还有一些自定义字段使 where 子句更加不可预测。而且,如果您在每次往返中针对大量行执行几次 count * where ... ,则无论索引如何,都会导致性能问题等,如果查询是可预测的或至少是简单的,则索引会这样做
    【解决方案2】:

    以下是加快数据层计数 (*) 的一些想法:

    1. 使表和聚集索引尽可能窄,以便每页容纳更多行
    2. 使过滤条件尽可能简单,以便快速计数
    3. 在开始计数之前,尽你所能确保要计数的行在内存中(可能使用预缓存)
    4. 确保您的硬件经过优化(足够的 RAM、足够快的磁盘等)
    5. 考虑在单独的表中缓存结果

    作为替代方案,如果只是过滤器频繁更改而不是数据本身,您可以考虑使用 Analysis Services 构建多维数据集,并针对它运行查询。

    【讨论】:

      猜你喜欢
      • 2012-06-23
      • 2012-06-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-06
      • 1970-01-01
      相关资源
      最近更新 更多