sourcetip

구분된 목록을 데이터베이스 열에 저장하는 것이 정말 그렇게 나쁜가요?

fileupload 2023. 9. 25. 22:55
반응형

구분된 목록을 데이터베이스 열에 저장하는 것이 정말 그렇게 나쁜가요?

확인란 집합이 있는 웹 양식을 상상합니다(모두 또는 임의의 확인란을 선택할 수 있습니다.데이터베이스 테이블의 한 열에 저장된 값의 쉼표로 구분된 목록에 저장하기로 선택했습니다.

이제 두 번째 테이블을 만들고 데이터베이스를 적절히 정규화하는 것이 올바른 해결책임을 알고 있습니다.쉬운 솔루션을 구현하는 것이 더 빨랐고, 애플리케이션에 너무 많은 시간을 들이지 않고도 애플리케이션에 대한 개념 증명을 신속하게 수행하고 싶었습니다.

저는 절약된 시간과 간단한 코드가 제 상황에서 가치가 있다고 생각했습니다. 이것이 방어 가능한 디자인 선택인가요, 아니면 처음부터 정규화했어야 했나요?

좀 더 맥락에 따라 공유 폴더에 저장되어 있던 Excel 파일을 근본적으로 대체하는 작은 내부 응용프로그램입니다.프로그램을 정리해서 유지보수를 좀 더 해볼까 해서 물어봅니다.그 안에는 제가 완전히 만족하지 않는 것들이 있는데, 그 중 하나가 이 질문의 주제입니다.

단일 열에 저장된 값의 반복 그룹으로 인해 First Normal Form을 위반하는 것 외에도 쉼표로 구분된 목록에는 더 실용적인 문제가 많이 있습니다.

  • 각 값이 올바른 데이터 유형인지 확인할 수 없음: 1,2,3,banana,5를 방지할 방법 없음
  • 외부 키 제약 조건을 사용하여 값을 조회 테이블에 연결할 수 없으며 참조 무결성을 적용할 방법이 없습니다.
  • 고유성을 적용할 수 없음: 1,2,3,3,3,5를 방지할 방법 없음
  • 전체 목록을 가져오지 않으면 목록에서 값을 삭제할 수 없습니다.
  • 문자열 열에 맞는 것보다 긴 목록을 저장할 수 없습니다.
  • 목록에서 지정된 값을 가진 모든 엔터티를 검색하기 어렵습니다. 비효율적인 테이블 스캔을 사용해야 합니다.MySQL해야 할
    idlist REGEXP '[[:<:]]2[[:>:]]'는 MySQL 8.0에서:idlist REGEXP '\\b2\\b'
  • 목록에서 요소를 세거나 다른 집계 쿼리를 수행하기가 어렵습니다.
  • 참조하는 룩업 테이블에 값을 조인하기가 어렵습니다.
  • 정렬된 순서대로 목록을 가져오기가 어렵습니다.
  • 값에 나타나지 않도록 보장된 구분 기호를 선택하기 어렵습니다.

이러한 문제를 해결하려면 수많은 애플리케이션 코드를 작성하여 RDBMS가 이미 제공하는 기능을 훨씬 효율적으로 재창조해야 합니다.

쉼표로 구분된 목록은 제 책의 첫 장을 만들 정도로 충분히 틀렸습니다.SQL 안티패턴, 1권: 데이터베이스 프로그래밍의 함정 피하기

정규화 해제를 사용해야 할 때도 있지만 @OMG Ponies가 언급한 것처럼 예외적인 경우입니다.관계가 없는 "최적화"는 데이터의 다른 용도에 비해 한 가지 유형의 쿼리에 도움이 되므로, 쿼리 중 어떤 것을 특별히 처리해야 하는지 알아야 합니다.

"한 가지 이유는 게으름이었습니다."

경보음이 울립니다.당신이 이런 일을 해야 하는 유일한 이유는 당신이 그것을 "올바른 방법"으로 할 줄 알지만, 당신은 그것을 그렇게 하지 말아야 할 가시적인 이유가 있다는 결론에 도달했기 때문입니다.

다음과 같이 말합니다. 이 방식으로 저장하기로 선택한 데이터가 결코 쿼리할 필요가 없는 데이터라면 선택한 방식으로 저장하는 경우가 있을 수 있습니다.

(일부 사용자는 이전 단락에서 "앞으로 어떤 요구사항이 추가될지 절대 알 수 없다"며 이의를 제기할 것입니다.이 사용자들은 잘못 판단했거나 종교적 확신을 말하고 있습니다.때로는 자신이 가지고 있는 요구사항에 따라 작업하는 것이 유리합니다.)

SO에 대한 질문은 다음과 같습니다.

  • 쉼표로 구분된 목록에서 특정 값의 개수를 가져오는 방법
  • 쉼표로 구분된 목록에서 2/3/etc 특정 값만 같은 레코드를 가져오는 방법

쉼표로 구분된 목록의 또 다른 문제는 값이 일치하는지 확인하는 것입니다. 텍스트 저장은 오타의 가능성을 의미합니다.

이는 모두 정규화되지 않은 데이터의 증상이며, 정규화된 데이터를 항상 모형화해야 하는 이유를 강조합니다.정규화 해제는 요구사항이 실제로 나타날 적용되는 쿼리 최적화가 될 수 있습니다.

일반적으로 어떤 것이든 프로젝트의 요구사항을 충족한다면 방어할 수 있습니다.그렇다고 해서 사람들이 당신의 결정에 동의하거나 방어하고 싶어하는 것은 아닙니다.

일반적으로 이러한 방식으로 데이터를 저장하는 것은 최적이 아니며(예: 효율적인 쿼리를 수행하기가 더 어려운 경우), 양식의 항목을 수정할 경우 유지보수 문제가 발생할 수 있습니다.중간 그라운드를 찾아서 대신 비트 플래그 집합을 나타내는 정수를 사용할 수도 있었겠죠?

네, 정말 그렇게 나쁘다고 생각합니다.그것은 방어할 수 있는 선택이지만, 그렇다고 해서 정확하거나 좋은 것은 아닙니다.

첫번째 정상적인 형태를 깨뜨립니다.

두 번째 비판은 검증이나 바인딩 없이 원시 입력 결과를 데이터베이스에 직접 입력하면 SQL 주입 공격에 노출된다는 것입니다.

여러분이 게으름과 SQL 지식 부족이라고 부르는 것은 초보자들이 만든 것입니다.시간을 내서 제대로 하고 배울 수 있는 기회로 여기는 것을 추천합니다.

아니면 그대로 두고 SQL 주입 공격의 뼈아픈 교훈을 배우십시오.

다중 값 열이 필요했습니다. xml 필드로 구현할 수 있습니다.

필요에 따라 쉼표로 구분하여 변환할 수 있습니다.

Xquery를 사용하여 sql 서버에서 XML 목록을 쿼리합니다.

xml 필드가 되면 몇 가지 우려 사항을 해결할 수 있습니다.

CSV 사용: 각 값이 올바른 데이터 유형인지 확인할 수 없음: 1,2,3,banana,5를 방지할 방법 없음

XML을 사용하면 태그의 값을 올바른 유형으로 강제 지정할 수 있습니다.


CSV 사용: 외부 키 제약 조건을 사용하여 값을 조회 테이블에 연결할 수 없으며 참조 무결성을 적용할 방법이 없습니다.

XML의 경우: 여전히 문제입니다.


CSV 사용: 고유성을 적용할 수 없음: 1,2,3,3,3,5를 방지할 방법 없음

XML의 경우: 여전히 문제입니다.


With CSV: 전체 목록을 가져오지 않으면 목록에서 값을 삭제할 수 없습니다.

XML을 사용하면 단일 항목 제거 가능


CSV 사용: 목록에서 지정된 값을 가진 모든 엔티티를 검색하기가 어렵습니다. 비효율적인 테이블 스캔을 사용해야 합니다.

XML을 사용하면 xml 필드를 인덱싱할 수 있습니다.


CSV 사용: 목록의 요소를 세거나 다른 집계 쿼리를 수행하기 어렵습니다.**

XML을 사용할 경우: 특별히 어렵지 않음


CSV 사용: 참조하는 룩업 테이블에 값을 조인하기 어렵습니다.**

XML을 사용할 경우: 특별히 어렵지 않음


CSV 사용: 정렬된 순서로 목록을 가져오기가 어렵습니다.

XML을 사용할 경우: 특별히 어렵지 않음


CSV 사용: 정수를 문자열로 저장하는 경우 이진 정수를 저장하는 경우보다 공간이 약 두 배 더 많이 소요됩니다.

XML을 사용하면 스토리지가 csv보다 더 열악함


CSV 사용: 많은 쉼표 문자를 추가합니다.

XML의 경우: 쉼표 대신 태그가 사용됩니다.


간단히 말해서, XML을 사용하면 구분 목록의 일부 문제를 해결하고 필요에 따라 구분 목록으로 변환할 수 있습니다.

네, 그 정도입니다.제 견해는 관계형 데이터베이스를 사용하는 것을 좋아하지 않는다면, 더 적합한 대안을 찾으라는 것입니다. 정말 고급 기능을 갖춘 흥미로운 "NOSQL" 프로젝트가 많이 있습니다.

SQL Server의 NTEXT 열에서 키/값 쌍 탭으로 구분된 목록을 4년 이상 사용해 왔는데 작동합니다.쿼리를 생성할 때 유연성을 잃기는 하지만, 반면에 키 값 쌍을 지속/지속하는 라이브러리가 있다면 이는 그리 좋은 생각이 아닙니다.

저는 아마 CSV의 각 필드를 데이터베이스의 별도 열로 만드는 중간 지점을 택할 것입니다. 하지만 (적어도 지금은) 정규화에 대해서는 크게 걱정하지 않습니다.어느 시점에서는 정규화가 흥미로워질 도 있지만, 모든 데이터를 단일 열에 밀어 넣음으로써 데이터베이스를 사용함으로써 얻을 수 있는 이점은 사실상 없습니다.데이터를 의미 있게 조작하기 위해서는 데이터를 논리적 필드/열/이름을 무엇이라 부르든지 구분해야 합니다.

만약 당신이 고정된 수의 부울 필드를 가지고 있다면, 당신은 다음을 사용할 수 있습니다.INT(1) NOT NULL(또는BIT NOT NULL우).CHAR (0) 대해 (null)한을 .SET(정확한 구문은 잊어버립니다.)

언급URL : https://stackoverflow.com/questions/3653462/is-storing-a-delimited-list-in-a-database-column-really-that-bad

반응형