나는 두 개의 테이블에서 모든 데이터를 가져 와서 어떤 것을 다시 계산하고 저장하는 클라이언트 - 서버 애플리케이션을 가지고있다.DB 디자인/대기 시간/동시성, 끔찍한 두통
예 :
각 항목이 '빌 재료」를 가지는 목록이 부족되어있는 다른 상품의 수량을 =. 따라서 항목 비용은 해당 항목의 BOM * 수량에 대한 비용 합계입니다. 궁극적으로 일부 "기본"항목에는 BOM이없고 비용 만 별도로 설정됩니다. (예 : 원자재)
예 : A의 BOM은 2xB 및 3xC로 구성됩니다.
내가 지금하고있는 것과 내가 왜 이런 식으로 기억하는지 모르겠다. DB에서 모든 항목과 모든 BOM을 가져 와서 재귀 적으로 비용을 계산할 때마다 각 항목을 가져 간다. 한 항목을 계산하면 다시 플래그를 다시 지정하지 않으므로 플래그를 지정합니다. (또한 무한 재귀를 막아 준다)
이것은 다소 어리석은 일이다 : 우선, 그 슬 루우와 변경되지 않은 물건을 다시 계산하고, 더 큰 DB를주고, 메모리가 부족할 것이다. .
대신 항목의 BOM이 변경되면 해당 BOM을 다시 계산 한 다음이 업데이트 된 항목이 포함 된 모든 BOM을 선택하고 다시 계산할 수도 있습니다. 린스 및 반복적으로 반복적으로 반복합니다. DB의 BOM은 변경된 항목에 따라 달라집니다.
실제로 의미하는 바는 일부 품목이 원자재이며 비용이 자주 업데이트 될 수 있으며 일부 품목은 "최종 사용자"물건이며 BOM은 거의 변경되지 않을 것이라고합니다. 사용자가 이러한 자료 중 하나의 비용을 변경하면 수천 개의 항목을 골라서 다시 계산할 수 있습니다. 1 항목/BOM의 SELECT가 15ms (Postgresql에 있음)를 선택한 다음 1000 항목/BOM을 선택하는 데 15 초가 걸린 다음 재 계산 된 비용을 DB의 항목으로 다시 업데이트해야한다고 ... 사랑 스러울 때 대기 시간은 이제 몇 분으로 바뀔 수 있습니다.
내가 사용하는 회사의 ERP 소프트웨어는 첫 번째 접근 방식을 취합니다. 전체 DB를 한 번에 다시 계산하십시오. 이것은 글자 그대로 몇 시간이 걸리며, 10 년 이상의 사용으로이 접근 방식으로 문제가 형성되고있는 것처럼 보입니다. 배치 재 계산은 매주 수행됩니다.
이제 실제로 "이 내용을 큰 소리로 써"보았으므로 몇 분이 지나면 문제가 너무 많다고 생각하지 않습니다. 문제는 데이터베이스를 잘 이해하지 못하기 때문에 동시성에 대해 걱정하고 있습니다. 항목 A에서 업데이트하는 데 오랜 시간이 걸리므로 누군가가 항목 A가있는 동안 두 번째 항목 B를 업데이트 할 가능성이 있습니다 업데이트되었습니다.
말 항목 D는 위의 A와 B로 구성됩니다. 사용자 1은 A를 업데이트하므로 서버 소프트웨어는 DB로 수음을 시작하여 결국 D를 업데이트합니다. 그러나 그 동안 사용자 2는 B를 업데이트하므로 결국 서버에서 D를 다시 업데이트합니다.
PostgreSQL의 트랜잭션을 사용하면 문제가 해결됩니까? 트랜잭션은 그 당시의 DB 상태로 시작하므로 트랜잭션 1은 D가 A1과 B1로 만들어지고 A가 A1에서 A2로 업데이트되는 것을 보지만 트랜잭션이 완료되고 커밋되기 전에 트랜잭션 2가 시작되고 A1도 보입니다. 및 B1. T1은 다시 계산하고 커밋하며 D = A2 + B1입니다. 그러나 T2는 이미 시작되었고 새로운 A, A2를 보지 못했습니다. 그래서 DB에 D = A1 + B2라는 커밋을합니다. 그것은 D = A2 + B2 여야합니다.
또한 일부 처리가 중복되어 서버 시간이 낭비됩니다.
평행 대신 T1과 T2를 순차적으로 수행하면 만세, 대답은 정확하지만 사용자 2는 더 오래 기다려야합니다. 또한, 트랜잭션 그룹이 서로 독립적이지 않은 경우 (즉, A = X + Y 및 B = N + M), 병렬 계산은 정답을 제공하고 사용자.
중요 사항 : 순차적으로 처리 할 때도 여전히 트랜잭션을 사용하므로 나머지 소프트웨어는 비용을 다시 계산하는 함수를 제외하고는 해당 데이터와 병렬로 계속 작동 할 수 있습니다.
DB 대기 시간이 너무 "끔찍한"것이 아니라면,이 모든 "순차적 처리"는 그렇게 나쁘지 않을 것입니다. 말하자면, 전체 데이터가 RAM에 저장된다면, 물마루 천 물체가 산들 바람이 될 것입니다. 아,하지만 디스크/RAM에서 /로 데이터를 빠르게 이동하고 DB를 대체하기 위해 캐싱을 수행하는 시스템을 구축하더라도 여전히 서버 기능의 나머지 부분을 처리 할 수 있도록 트랜잭션이 필요하기 때문에 그렇게하지 않을 것입니다. 병렬로 작업 할 수 있습니다. (위의 '중요한 메모') 그래서 나는 또 다른 DB를 구축하게 될 것입니다. 조금 더 빨라지 겠지만 어리석은/시간 낭비.
각 항목의 비용을 "캐시"하는 이유는 제한된 리소스를 낭비 할뿐만 아니라 DB 대기 시간이 너무 크고 동시성 문제이기 때문에 사용할 때마다 다시 계산하지 않기 때문입니다. 규모가 더 나 빠졌다.
이제 "그들이"큰 일괄 처리를 한 이유가 무엇인지 궁금 할 필요가 없습니다 ... 이것은 내 머리를 아프게하고 있습니다.
Q1 : 어떻게 당신이 "최적"의 방법으로이 문제를 해결합니까?
내 이해 (즉, 내가 조용히 무시하기 전에 동시성 문제에 직면 한 후), 나는 그 함수가 순차적으로 트랜잭션을 사용하도록 만들 것이고, 나머지 응용 프로그램은 여전히 데이터를 사용할 수 있습니다. 평행, 내가 믿는 사용자에게 가장 좋습니다. 그게 목표입니다. 사용자에게는 가장 좋지만 시스템에 대한 정확성은 보장됩니다.
어쩌면 나중에 하드웨어를 던져서 소프트웨어 블랙 매직을 사용하여 지연 시간을 줄일 수 있지만 지금은 스스로 거짓말하기 시작합니다.
지난 두 달 동안 나는 프로그래밍에 관련되지 않은 여러 가지 명백한 일들에 대해 완전히 눈이 멀었습니다. 그래서 누군가 내가 부끄러워 보이는 것을 지적 할 것입니다. 놓치다 : ... |
그는 한 지점에서 "나는 PostgreSQL에있다"고 언급하고 있습니다 ... –
죄송합니다! 나는 그것을 놓쳤다. –