Mysql 하위 선택이 매우 느립니다.
저는 이런 테이블이 있습니다.
-------------------------------
| id | valid_until | username|
-------------------------------
| 1 | 2020-01-01 | user1 |
-------------------------------
| 1 | 2020-01-01 | user2 |
-------------------------------
| 1 | 2020-01-02 | user3 |
-------------------------------
| 1 | 2020-01-02 | user4 |
-------------------------------
| 1 | 2020-01-03 | user5 |
-------------------------------
| 1 | 2020-01-03 | user6 |
-------------------------------
| 1 | 2020-01-03 | user7 |
-------------------------------
이것이 사용자 등록 테이블입니다.valid_until
구독이 종료되는 시점을 나타냅니다.
매일 활성 구독을 알고 싶어서 범위가 있습니다. 예를 들어,2020-01-01
로.2020-01-03
제 질문은 이렇습니다.
SELECT
valid_until qva,
(SELECT
COUNT(iod.id) AS ct
FROM
`order_detail` iod
WHERE
valid_until > qva)
FROM
`order_detail`
WHERE
valid_until >= '2020-01-01'
AND valid_until <= '2020-01-03'
GROUP BY qva
하지만 이 쿼리가 너무 느립니다. 내 쿼리에 무슨 문제가 있습니까?응답시간(230초)
SQL 표준에 따라 쿼리가 잘못되었습니다.당신은 가지고 있다GROUP BY qva
(그리고 여기서 별칭 이름을 사용하는 것은 일반적으로 허용되지 않지만 MySQL 및 MariaDB에서는 허용됨) 그러나 하위 쿼리 결과에는 집계 함수를 적용하지 않습니다.MySQL은 표준을 위반한 것으로 알려져 있으며 이들은 묵묵히 적용됩니다.ANY_VALUE
이런 비집고적인 표현으로
이렇게 하면 쿼리 속도가 느려집니다.날짜 범위의 각 순서에 대해 카운트를 평가하고 맨 끝에 있는 날짜당 카운트 중 하나만 선택합니다.
그럼 처음부터 다시 쿼리를 만들어 보겠습니다.지정된 날짜 범위에서 각 날짜에 대해 하나의 결과 행을 사용하려고 합니다.즉,
select distinct valid_until
where valid_until between date '2020-01-01' and date '2020-01-03'
from order_detail;
그런 다음 이 날짜마다 카운트를 구합니다.원래 쿼리와 같이 하위 쿼리에서 이 작업을 수행할 수 있습니다.제 생각에는 그럴 것 같습니다.>=
대신에>
하지만 그날 하루까지 유효한 주문(또는 적어도 이것이 내가 예상했던 것입니다).
SELECT
dates.day,
(
select count(*)
from order_detail od
where od.valid_until >= dates.day
) as ct
FROM
(
select distinct valid_until as day
where valid_until between date '2020-01-01' and date '2020-01-03'
from order_detail
) dates
order by dates.day;
(이것은 다음을 가정합니다.valid_until
단순한 데이트일 뿐입니다.날짜 시간이면 이 쿼리를 조금 조정해야 합니다.)
업데이트:
요청 주석에서 ysth가 알려준 것처럼 쿼리는 다음과 같이 존재하는 주어진 범위의 일만을 얻을 수 있습니다.valid_until
당신 테이블에.저도 그렇습니다.상관없이 3일을 원한다면 하위 쿼리를 교체하고 테이블에서 독립적으로 만들어야 합니다.
FROM
(
select date '2020-01-01' as day union all
select date '2020-01-02' as day union all
select date '2020-01-03' as day
) dates
내 생각엔 당신은 단지 당신이 원하는 것은valid_until
최신 날짜부터 가장 빠른 날짜까지:
select valid_until, count(*) day_count,
sum(count(*)) over (order by valid_until desc) as count_as_of_day
from order_details od
group by valid_until;
날짜 범위에 대해 원하는 경우 하위 쿼리를 사용합니다.
select od.*
from (select valid_until, count(*) day_count,
sum(count(*)) over (order by valid_until desc) as count_as_of_day
from order_details od
group by valid_until
) od
where valid_until >= :from and valid_until <= :to
언급URL : https://stackoverflow.com/questions/63868917/mysql-sub-select-is-very-slow
'programing' 카테고리의 다른 글
C 복합 리터럴, 배열 포인터 (0) | 2023.09.26 |
---|---|
CORS 및 Access-Control-Allow-Header는 어떻게 작동합니까? (0) | 2023.09.26 |
Laravel 마이그레이션 기본(또는 키) "식별자 이름이 너무 깁니다." (0) | 2023.09.26 |
MySQL의 다른 일부 열과 함께 고유 열 선택 (0) | 2023.09.26 |
C vs C++ 사이즈의 (0) | 2023.09.26 |