包含大量数据的表,是否有人知道如何优化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)。
感谢您的任何建议。
答案 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_email
和p_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;