2017-11-18 103 views
0

有大数据的表,有人知道如何优化count语句吗?例如:表预订(ID,电子邮件,手机,...)(约30个字段)。Oracle - 在有大量数据的表上需要多次计数的建议

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子句中算作电子邮件列,移动,状态栏什么的字段列索引。

解决方案2:创建一个包含少量列的新表。 新表:Booking_Stats(id,电子邮件,手机,状态)。

感谢您的任何建议。

回答

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; 
+0

谢谢,但你的SQL可能是错误的,不工作,请参阅oracle中的sql – hungudgm

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 

//注意:(电子邮件,移动查询从头写的,没有测试

你会考虑创建上(电子邮件,手机)或索引,状态)取决于你得到的给定(电子邮件,移动设备)的行数,你将支付更新状态改变索引的费用(如果允许的话)。如果同一行的状态有很多更新,您可能更喜欢仅索引(电子邮件,手机)[读/写成本折衷]。

电子邮件很可能是非常区分的(一个值会过滤大部分列)。如果不是这种情况,请考虑将订单更改为(手机,电子邮件),如果移动列是更好的候选人。

+0

感谢您的详细知识,但您的SQL也相同我的解决方案1 ​​ – hungudgm

+0

@hungudgm好吧,我没有从问题中推论出来。那将是你情况最好的方式。 – igr

1

似乎所有这些功能都没有帮助,实际上对性能无害。

您还没有发布一套完整的要求(什么是...意思?),所以这是很难确定的,但它很可能是沿着这些路线的解决方案会更表演:

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中的每一个都有不同的查询,单列索引支持每个查询。