실패한 channel_jobs 가 이관된 상품에 걸린 것인지를 판별해야 했다. migration_log 가 있으니 그것과 JOIN 하면 되는 간단한 일로 보였다.
Table of contents
Open Table of contents
문제 — 계속 나온 0건
JOIN 해서 세니 0건이 나왔고 조건을 바꾸거나 날짜를 넓혀도 계속 0이었다. 이관된 상품이 하나도 없다고 결론 내려던 참에 정말 없는지 DESC 로 컬럼 구조를 확인했느냐는 지적을 받았다.
그 확인을 하지 않은 상태였다. 컬럼 이름이 둘 다 product_id 니 그대로 조인되겠거니 하고 넘어간 것이다.
원인 — 두 단계였던 구조
DESC products 로 컬럼 목록을 확인하니 parent_id 가 따로 있었다. 그것을 넣어 구조를 정리하니 신규 자식 상품이 parent_id 로 마스터를 가리키고 migration_log.product_id 가 그 마스터 식별자를 담고 있었다.
그런데 channel_jobs.product_id 는 마스터가 아니라 자식 상품을 가리키고 있었다. 자식 식별자를 마스터 식별자 컬럼에 조인했으니 0건이 나오는 것이 당연했다.
정반대가 된 결과
그래서 중간에 products 를 끼워 JOIN products p ON p.id = j.product_id JOIN migration_log m ON m.product_id = p.parent_id 로 한 단계를 더 거쳐 조인하도록 고쳤다. 다시 세니 대상 작업이 수천 건이었고 그중 대부분이 이관 대상이었다.
이관된 것이 없는 것이 아니라 거의 전부가 이관된 것이었고 결론이 정반대로 뒤집혔다.
주의 — 0건이 주는 느낌
이 일이 보여 주는 것은 조회 결과 0건이 두 가지를 뜻한다는 점이다. 정말 없는 경우와 조회가 틀린 경우인데 결과만 놓고 보면 둘이 구분되지 않는다.
그리고 0건이라는 결과는 무언가를 확인했다는 느낌을 준다. 쿼리가 정상으로 돌았고 결과까지 나왔기 때문이다. 오류가 났으면 다시 봤을 텐데 0건은 그대로 넘어가게 되므로 더 위험하다.
판단 기준 — 0건일 때의 절차와 순서
두 가지 방법이 있었는데 0건이 나오면 조건을 넓혀 다시 세는 것과 JOIN 을 하나씩 떼어 어디서 0 이 되는지 보는 것이다. 뒤쪽을 골랐다. 이유는 조건을 넓히는 것은 틀린 조인 위에서 계속 세는 것이라서다. 대신 조인 수만큼 쿼리를 더 돌리는 수고를 감수했다. 조인 없이 세면 수천 건인데 조인 하나를 붙이자마자 0이 되면 그 조인 조건이 틀린 것이다.
근본 원인은 두 컬럼이 다 product_id 인데 가리키는 계층이 다르다는 것이었고 이름이 계층을 알려 주지 않는다. 계층 구조가 있는 스키마에서는 그 식별자가 어느 층인지를 항상 확인해야 하며 조인 전에 DESC 한 번이면 되는 일을 이름으로 추측한 것이 이 조사의 실수였다.
정리
- 0건은 없다와 조회가 틀렸다를 구분하지 못한다
- 0건은 오류와 달리 확인했다는 느낌을 준다
- 0건이 나오면
JOIN조건을 하나씩 떼어 본다 - 어디서 0이 되는지 보면 그 조인이 문제다
- 계층이 있는 스키마에서 같은 이름이 다른 층을 가리킬 수 있다
- 작업 테이블의 식별자가 마스터가 아니라 자식일 수 있다
- 한 단계 거쳐 조인해야 하는 경우가 있다
- 조인 전에
DESC로 스키마를 보고 이름으로 추측하지 않는다