【问题标题】:Oracle - Need advice on multiple counts, on table with large amounts of data甲骨文 - 需要关于多个计数的建议,在有大量数据的表上
【发布时间】:2018-05-01 22:45:44
【问题描述】:

大数据表,有谁知道怎么优化count语句?

例如:表 Booking(id, email, mobile,....)(大约 30 个字段)。

Function GetBookingCount(p_email, p_mobile) return number
    Select count(id) 
    from Booking 
    Where email = p_email 
    or mobile = p_mobile

Function GetBookingStatus3Count(p_email, p_mobile) return number
    Select count(id) 
    from Booking
    Where (email = p_email or mobile = p_mobile) 
    and status = 3;

最终选择:

Select GetBookingCount(email, mobile) as BookingCount
      , GetBookingStatus3Count(email, mobile) as BookingStatus3Count
      , ...
From Booking
where ....

解决方案1:在where子句中设置字段列索引what为email列、mobile、status列。

解决方案2:创建一个包含几列要计数的新表。 新表:Booking_Stats(id, email, mobile, status)。

感谢您的任何建议。

【问题讨论】:

    标签: sql oracle performance plsql


    【解决方案1】:

    预订表应该有一个关于电子邮件、手机和状态的索引。你应该使用这个选择:

        WITH B1 AS
    (
         SELECT ID,
                COUNT(ID) CNT1,
                STATUS
         FROM BOOKING
         WHERE EMAIL = P_EMAIL
               AND MOBILE = P_MOBILE
    )
    SELECT CNT1,
           COUNT(ID) CNT2
    FROM B1
    WHERE STATUS = 3;
    

    【讨论】:

    • 谢谢,但是你的sql可能不对,不工作,请看oracle中的sql
    【解决方案2】:
    select count(*) count_all, count( case when status=3 then 1 else null end ) count_status_3
    from Booking
    where email = p_email and mobile = p_mobile 
    

    //注意:查询是从头写入的,未经测试

    您会考虑在 (email,mobile) 或 (email,mobile,status) 上创建索引,具体取决于您获得的给定 (email,mobile) 的行数,并且您会支付更新状态索引的费用更改(如果允许)。如果同一行有许多状态更新,您可能更喜欢仅索引(电子邮件、移动)[读/写成本权衡]。

    电子邮件可能非常具有辨别力(一个值会过滤掉大部分列)。如果不是这种情况,如果移动列是更好的候选者,请考虑将顺序更改为 (mobile,email)。

    【讨论】:

    • 感谢您提供详细的知识,但您的 sql 也与我的解决方案相同 1
    • @hungudgm 好的,我没有从问题中推断出来。在您的情况下,这将是最好的方法。
    【解决方案3】:

    似乎所有这些 GetBookingBlahBlah() 函数都没有帮助,实际上对性能有害。

    您还没有发布完整的需求集(... 是什么意思?),所以很难确定,但似乎按照这些思路的解决方案可能会更具性能:

    with bk as (
        select *
        from booking 
        where email = p_email 
        or mobile = p_mobile
    )
    select count(*) as BookingCount
           , count(case when bk.status = 3 then 1 end) as BookingStatus3Count
           , ...
    from bk
    

    这个想法是查询基表一次,获取计算所有计数所需的所有数据,并在可能的最小结果集上处理聚合。

    booking(email,mobile) 上的索引可能有用但可能没有用。更好的解决方案是对 p_emailp_mobile 分别使用不同的查询,并使用单列索引支持每个查询。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-10-05
      • 1970-01-01
      • 2018-01-21
      • 1970-01-01
      • 1970-01-01
      • 2014-12-26
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多