Очень медленный запрос при фильтрации - PullRequest
1 голос
/ 22 октября 2019

У меня есть таблица INVESTOR_OPPORTUNITY, которая структурирована следующим образом:

- ID        // PRIMARY KEY
- INVESTOR_ID
- OPPORTUNITY_ID
- POINTS    // values 0 to 5

ИНВЕСТОР может быть связан с одной и той же возможностью несколько раз, и на каждую возможность обычно приходится 10000 инвесторов. Таким образом, в среднем на каждую возможность приходится около 20 000 строк.

В моем 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']);

Я попробовал комбинацию индексов (INVESTOR_ID: OPPORTUNITY_ID: POINTS), ноне повезло.

Как я могу оптимизировать этот запрос ??

Любая помощь приветствуется.

...