Oracle - 需要多个计数的建议,包含大量数据

时间:2017-11-18 05:21:44

标签: sql oracle performance plsql

包含大量数据的表,是否有人知道如何优化count语句?

例如:表格预订(身份证,电子邮件,手机,......)(约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 ....

solution1:设置字段列索引where子句中的内容,将其计为电子邮件列,移动,状态列。

solution2:创建一个包含少量列的新表。 新表:Booking_Stats(id,email,mobile,status)。

感谢您的任何建议。

3 个答案:

答案 0 :(得分:1)

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 

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

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

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

答案 1 :(得分:1)

似乎所有这些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中的每一个提供不同的查询,其中单列索引支持每个查询。

答案 2 :(得分:0)

预订表应包含电子邮件,移动设备和状态索引。你应该使用这个选择:

    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;