Plsql 过滤时查询速度非常慢
我有一个table INVESTOR_OPPORTUNITY,其结构如下:Plsql 过滤时查询速度非常慢,plsql,yii2,sql-optimization,Plsql,Yii2,Sql Optimization,我有一个table INVESTOR_OPPORTUNITY,其结构如下: - ID // PRIMARY KEY - INVESTOR_ID - OPPORTUNITY_ID - POINTS // values 0 to 5 一个投资者可以多次与同一个机会关联,每个机会通常有10000名投资者。因此,平均每个opportunity大约有20000行 在我的GridView中,我需要为每个投资者显示一行,其中包含得分为1、2、3、4、5的机会计数。大概是这样的: INVE
- ID // PRIMARY KEY
- INVESTOR_ID
- OPPORTUNITY_ID
- POINTS // values 0 to 5
一个投资者可以多次与同一个机会关联,每个机会通常有10000名投资者。因此,平均每个opportunity大约有20000行
在我的GridView中,我需要为每个投资者显示一行,其中包含得分为1、2、3、4、5的机会计数。大概是这样的:
INVESTOR_ID | count of 1pt | count of 2pt | etc
123456 | 7 | 13 | etc
以下是查询的主要部分:
->select([
'INVESTOR_ID',
'SUM( CASE WHEN OPP.POINTS=0 THEN 1 ELSE 0 END) AS countPoints0',
'SUM( CASE WHEN OPP.POINTS=1 THEN 1 ELSE 0 END) AS countPoints1',
'SUM( CASE WHEN OPP.POINTS=2 THEN 1 ELSE 0 END) AS countPoints2',
'SUM( CASE WHEN OPP.POINTS=3 THEN 1 ELSE 0 END) AS countPoints3',
'SUM( CASE WHEN OPP.POINTS=4 THEN 1 ELSE 0 END) AS countPoints4',
'SUM( CASE WHEN OPP.POINTS=5 THEN 1 ELSE 0 END) AS countPoints5',
])
->andWhere([OPPORTUNITY_ID=>$this->OPPORTUNITY_ID])
->groupBy(['INVESTOR_ID']);
这往往工作得很好,而且速度相当快。但是,只要我在其中一个计数中筛选出一个值,查询就可能需要17秒以上,有时甚至超过一两分钟
例如:如果我想看到所有拥有1个以上机会且得分为零的投资者:
->select([
'INVESTOR_ID',
'SUM( CASE WHEN OPP.POINTS=0 THEN 1 ELSE 0 END) AS countPoints0',
'SUM( CASE WHEN OPP.POINTS=1 THEN 1 ELSE 0 END) AS countPoints1',
'SUM( CASE WHEN OPP.POINTS=2 THEN 1 ELSE 0 END) AS countPoints2',
'SUM( CASE WHEN OPP.POINTS=3 THEN 1 ELSE 0 END) AS countPoints3',
'SUM( CASE WHEN OPP.POINTS=4 THEN 1 ELSE 0 END) AS countPoints4',
'SUM( CASE WHEN OPP.POINTS=5 THEN 1 ELSE 0 END) AS countPoints5',
])
->having('SUM( CASE WHEN OPP.POINTS=0 THEN 1 ELSE 0 END) >1')
->andWhere([OPPORTUNITY_ID=>$this->OPPORTUNITY_ID])
->groupBy(['INVESTOR_ID']);
我尝试了多种指数组合(投资者ID:OPPORTUNITY\ID:POINTS),但运气不佳
如何优化此查询
谢谢你的帮助 首先,在使用having子句进行筛选之前,您有多少行??第二,您正在使用activerecord??显示查询代码的其余部分我不确定,但也许您可以用
和where(['OPP.POINTS'=>0])
替换having
?结果应该是相同的,但您现在可以使用索引。我想你最好用5列0/1的值来表示点,而不是每次只处理一列。@Bizley不会给出相同的结果,因为如果使用AND,则OPP.POINTS
中具有不同值的行将在groupby
之前过滤掉,因此countPoints1-countpoints5将始终为空。但是它可以在子查询中使用,比如$subquery=…->选择(['INVESTOR\u ID'])->where(['OPP.POINTS'=>0,'OPPORTUNITY\u ID'=>$this->OPPORTUNITY\u ID])
然后在主查询中使用此子查询->和where(['in','INVESTOR\u ID',$subquery])
而不是使用。这将允许使用索引。@MichalHynčica是的,你说得对。我仍然会选择5列而不是一列。@scaisEdge是的,我正在使用activeRecord。最好的选择是什么?首先,在使用having子句进行筛选之前,您有多少行??第二,您正在使用activerecord??显示查询代码的其余部分我不确定,但也许您可以用和where(['OPP.POINTS'=>0])
替换having
?结果应该是相同的,但您现在可以使用索引。我想你最好用5列0/1的值来表示点,而不是每次只处理一列。@Bizley不会给出相同的结果,因为如果使用AND,则OPP.POINTS
中具有不同值的行将在groupby
之前过滤掉,因此countPoints1-countpoints5将始终为空。但是它可以在子查询中使用,比如$subquery=…->选择(['INVESTOR\u ID'])->where(['OPP.POINTS'=>0,'OPPORTUNITY\u ID'=>$this->OPPORTUNITY\u ID])
然后在主查询中使用此子查询->和where(['in','INVESTOR\u ID',$subquery])
而不是使用。这将允许使用索引。@MichalHynčica是的,你说得对。我仍然会选择5列而不是一列。@scaisEdge是的,我正在使用activeRecord。最好的选择是什么?