문제

자, 사실상 모든 데이터베이스 기반 애플리케이션은 "비활성" 레코드를 처리해야 합니다.소프트 삭제 또는 "무시"로 표시하는 것입니다.'활성' 열(또는 상태 열)에 대한 급진적인 대안 생각이 있는지 궁금합니다.

예를 들어, 사람 목록이 있다면

CREATE TABLE people (
  id       INTEGER PRIMARY KEY,
  name     VARCHAR(100),
  active   BOOLEAN,
  ...
);

이는 활동적인 사람들의 목록을 얻으려면 다음을 사용해야 함을 의미합니다.

SELECT * FROM people WHERE active=True;

비활성 레코드를 별도의 테이블로 옮기고 둘을 결합하기 위해 적절한 UNION이 수행될 것이라고 제안하는 사람이 있습니까?

호기심이 폭발한다...

편집하다: 나는 이것을 순수주의적 관점에서 접근하고 있다는 점을 분명히 해야 합니다.대량의 데이터에 데이터 보관이 어떻게 필요할 수 있는지 알 수 있지만 그것이 제가 원하는 곳은 아닙니다.SELECT * FROM people을 수행하면 해당 항목이 어떤 의미에서 "활성"이라는 것이 이해가 됩니다.

감사해요

도움이 되었습니까?

해결책

활성 플래그에 따라 테이블을 분할하여 활성 레코드가 한 파티션에 있고 비활성 레코드가 다른 파티션에 있도록 합니다.그런 다음 자동으로 활성 필터가 있는 각 테이블에 대한 활성 보기를 만듭니다.데이터베이스 쿼리 엔진은 활성 레코드가 있는 파티션으로 쿼리를 자동으로 제한합니다. 이는 해당 플래그에 인덱스를 사용하는 것보다 훨씬 빠릅니다.

다음은 Oracle에서 분할된 테이블을 생성하는 방법에 대한 예입니다.Oracle에는 부울 열 유형이 없으므로 Oracle용으로 테이블 구조를 수정했습니다.

CREATE TABLE people
(
   id       NUMBER(10),
   name     VARCHAR2(100),
   active   NUMBER(1)
)
PARTITION BY LIST(active)
(
   PARTITION active_records VALUES (0)
   PARTITION inactive_records VALUES (1)
);

원하는 경우 각 파티션을 서로 다른 테이블스페이스에 배치할 수 있습니다.인덱스를 분할할 수도 있습니다.

그러고 보니 이런 일이 반복되는 것 같다. 이것 질문, 초보자로서 제가 묻고 싶은 것은 의도하지 않은 중복을 처리하는 절차는 무엇입니까?

편집하다: 의견에서 요청한 대로 Oracle에서 분할된 테이블을 생성하는 예를 제공했습니다.

다른 팁

대부분의 상황에서 활성 레코드만 그리려면 활성 레코드만 포함하는 보기를 생성하면 됩니다.이렇게 하면 활성 부분을 생략하지 않는 것이 훨씬 쉽습니다.

우리는 대부분의 테이블에서 enum('ACTIVE','INACTIVE','DELETED')를 사용하므로 실제로 3방향 플래그가 있습니다.나는 그것이 다양한 상황에서 우리에게 잘 작동한다고 생각합니다.귀하의 마일리지가 다를 수 있습니다.

비활성 항목을 이동하는 것은 일반적으로 어리석은 생각입니다.버그가 발생할 가능성이 많아 오버헤드가 많이 발생하고, 항목을 보관 취소하는 등 모든 것이 더욱 복잡해집니다.관련 데이터로 무엇을 하시나요?해당 항목도 모두 이동하면 쿼리 하나하나를 모두 수정해야 합니다.움직이지 않으면 어떤 이점을 얻으려고 했나요?

이는 다음 사항으로 이어집니다.왜 그것을 옮기겠습니까?적절하게 인덱싱된 테이블은 크기가 두 배로 늘어날 때 한 번의 추가 조회가 필요합니다.성능 향상은 무시할 수 있습니다.그리고 실제로 성능 문제가 발생하는 먼 미래의 시간까지 왜 그것에 대해 생각하겠습니까?

엄밀히 말하면 데이터의 일부로 보면 원본 게시물에 표시된 방식이 적절하다고 생각합니다.활성 플래그 데이터 부분은 기본 키에 직접적으로 종속되며 테이블에 있어야 합니다.

해당 테이블은 데이터의 현재 상태에 관계없이 사람에 대한 데이터를 보유합니다.

활성 플래그는 보기 흉하지만 간단하고 잘 작동합니다.

제안한 대로 다른 테이블로 이동할 수 있습니다.활성/비활성 레코드의 비율을 살펴보는 것이 좋습니다.비활성 기록이 20~30% 이상인 경우 해당 기록을 다른 곳으로 옮기는 것을 고려할 수 있습니다.그렇지 않으면 큰 문제가 아닙니다.

예, 그렇습니다.현재 많은 테이블에 주로 '최신' 행을 표시하기 위해 "active='T/F'" 열이 있습니다.새 행이 삽입되면 이전 T 행은 F로 표시되어 감사 목적으로 유지됩니다.

이제 새 행이 삽입되면 이전 행이 기록 테이블로 이동하는 2테이블 접근 방식으로 전환하고 있습니다.이를 통해 현재 데이터를 살펴보면 대부분의 경우 더 나은 성능을 얻을 수 있습니다.

비용은 이전 방법보다 약간 더 높습니다. 이전에는 업데이트하고 삽입해야 했지만 이제는 삽입하고 업데이트해야 합니다(즉, 새 T 행을 삽입하는 대신 모든 새 데이터로 기존 행을 수정함). 변경 사항만 전달하는 대신 전체 데이터 행을 전달하는 것입니다.그러면 거의 효과가 없을 것입니다.

성능상의 이점은 기본 테이블의 인덱스가 훨씬 더 작으며 테이블스페이스를 더 잘 최적화할 수 있다는 것입니다(그렇게 많이 늘어나지는 않습니다!).

스키마에서 이와 같은 바이너리 플래그는 나쁜 아이디어입니다.쿼리를 고려해보세요

SELECT count(*) FROM users WHERE active=1

충분히 단순해 보입니다.그러나 사용자 수가 너무 많아 이 테이블에 인덱스를 추가해야 하는 경우에는 어떻게 될까요?또 다시 앞이 보인다

ALTER TABLE users ADD INDEX index_users_on_active (active)

제외하고!!이 열의 카디널리티가 정확히 2이기 때문에 이 인덱스는 쓸모가 없습니다!모든 데이터베이스 쿼리 최적화 프로그램은 카디널리티가 낮기 때문에 이 인덱스를 무시하고 테이블 스캔을 수행합니다.

유용한 플래그로 스키마를 채우기 전에 해당 데이터에 액세스하는 방법을 고려하십시오.

https://stackoverflow.com/questions/108503/mysql-advisable-number-of-rows

우리는 active flag를 꽤 자주 사용합니다.하지만 데이터베이스가 매우 커질 경우 비활성 값을 별도의 테이블로 마이그레이션하는 것이 가치가 있음을 알 수 있습니다.

그런 다음 누군가가 활성 또는 비활성 모든 레코드를 보려는 경우에만 테이블 통합이 필요합니다.

대부분의 경우 삭제를 나타내는 이진 필드이면 충분합니다.특정 시간이 지나면 삭제된 레코드를 제거하는 정리 메커니즘이 있는 경우가 많으므로 삭제된 타임스탬프를 사용하여 스키마를 시작하는 것이 좋습니다.

별도의 테이블로 이동하고 다시 가져오는 데 시간이 걸립니다.오프라인 상태가 되는 레코드 수와 해당 레코드를 다시 가져와야 하는 빈도에 따라 좋은 생각일 수도 있고 아닐 수도 있습니다.

일단 묻힌 후에 대부분이 다시 돌아오지 않고 요약/보고서/무엇이든 간에만 사용된다면 기본 테이블이 더 작아지고 쿼리가 더 간단해지고 더 빨라질 것입니다.

우리는 비활성 기록을 처리하기 위해 두 가지 방법을 모두 사용합니다.우리가 사용하는 방법은 상황에 따라 다릅니다.본질적으로 조회 값인 레코드의 경우 활성 비트 필드를 사용합니다.이를 통해 항목이 사용되지 않도록 비활성화할 수 있을 뿐만 아니라 관계와 데이터 무결성을 유지할 수도 있습니다.

데이터가 더 이상 필요하지 않고 데이터가 관계의 일부가 아닌 경우 "분리 테이블로 이동" 방법을 사용합니다.

상황이 실제로 해결책을 결정한다고 생각합니다.

테이블에 사용자가 포함된 경우 여러 "플래그" 필드를 사용할 수 있습니다.하나는 삭제됨, 비활성화됨 등입니다.또는 공간이 문제인 경우 비활성화 플래그로 충분하며 행이 삭제된 경우 실제로 행을 삭제합니다.

또한 데이터 저장 정책에 따라 다릅니다.데이터를 보관하기 위한 정책이 있는 경우 오랜 시간이 지나면 별도의 테이블이 필요할 가능성이 높습니다.

아니요 - 이것은 매우 일반적인 일입니다. 특정 요구 사항에 따라 몇 가지 변형이 있습니다(그러나 이미 다루었습니다).

1) 전체 데이터 묶음(예: 여러 테라바이트 이상)이 있을 것으로 예상되는 경우 삭제된 레코드를 즉시 보관하는 것은 나쁜 생각이 아닙니다. 하지만 삭제된 것으로 표시한 다음 보관 테이블에 복사하는 조합 접근 방식을 사용할 수도 있습니다.

2) 물론 기록을 영구 삭제할 수 있는 옵션은 여전히 ​​존재합니다. 비록 우리 개발자들은 데이터 수집에 열중하는 경향이 있지만, 비즈니스 프로세스를 살펴보고 지금 데이터를 보관해야 할 필요가 있는지 결정하는 것이 좋습니다. 있어요- 그렇게 하세요...그렇지 않다면 특정 비즈니스 시나리오에 따라 물건을 그냥 버려도 괜찮을 것입니다. 다시 한 번 말하지만.

'순수주의적 관점'에서 현실 모델은 뷰와 테이블을 구분하지 않습니다. 둘 다 관계입니다.따라서 판별자를 사용하는 뷰를 사용하는 것은 엔터티의 이름이 올바르게 지정된 경우 완벽하게 의미 있고 유효합니다.개인/활성 개인.

또한 '순수주의적 관점'에서 테이블 이름은 people이 아니라 person으로 지정해야 합니다. 관계 이름은 전체 집합이 아니라 튜플을 반영하기 때문입니다.

부울 인덱싱과 관련하여 다음과 같은 이유는 없습니다.

ALTER TABLE users ADD INDEX index_users_on_active (id, active) ;  

그러면 검색이 향상되지 않을까요?
그러나 그 대답 중 얼마나 많은 부분이 플랫폼에 따라 달라지는지는 모르겠습니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top