관계 데이터베이스의 실체 속성 값 모델.책상 위에서 글로벌스를 시뮬레이션해야 합니까?제2부분.

9010 단어 eavschemeglobalssql

더욱 공업적인 외관을 가진 글로벌 저장 방안


본 시리즈의 첫 번째 글에서 우리는 관계 데이터베이스에 있는 실체-속성-값(entity-attribute-value, EAV) 모델을 연구하고 이러한 실체, 속성과 값을 표에 저장하는 이해득실을 연구했다.우리는 비록 이런 방법은 유연성에 좋은 점이 있지만, 특히 데이터의 논리 구조와 물리적 저장 사이에 기본적으로 일치하지 않는 단점이 존재하기 때문에 각종 어려움을 초래한다는 것을 안다.
이러한 문제점을 해결하기 위해 EAV 방법이 일반적으로 처리하는 작업에서 글로벌스를 사용하는 것이 유효한지 확인하기로 결정했습니다. 글로벌스는 층별 정보를 저장하기 위해 최적화된 것입니다.
년, 우리는 온라인 상점을 위해 디렉터리를 만들었는데, 먼저 시계를 사용한 다음에 전체 시계만 사용했다.이제 몇 개의 전역 함수를 위해 같은 구조를 실현해 봅시다.
첫 번째 글로벌 파일 ^catalog에는 디렉토리 구조가 저장됩니다.두 번째 전 세계 창고 ^good에 우리는 화물을 저장할 것이다.글로벌 ^index에는 색인이 저장됩니다.우리의 속성은 차원 디렉터리에 연결되어 있기 때문에, 우리는 그것들을 위해 단독 전역 디렉터리를 만들지 않을 것입니다.
이런 방법을 통해 모든 실체(속성 제외)에 대해 우리는 하나의 단독 전역을 가지고 논리적인 측면에서 보면 이것은 매우 좋다.다음은 글로벌 카탈로그 구조입니다.

 
Set ^сatalog(root_id, "Properties", "capacity", "name") = "Capacity, GB"
Set ^сatalog(root_id, "Properties", "capacity", "sort") = 1

Set ^сatalog(root_id, sub1_id, "Properties", "endurance", "name") = "Endurance, TBW"
Set ^сatalog(root_id, sub1_id, "Properties", "endurance", "sort") = 2

Set ^сatalog(root_id, sub1_id, "goods", id_good1) = 1
Set ^сatalog(root_id, sub1_id, "goods", id_good2) = 1

Set ^сatalog(root_id, sub2_id, "Properties", "avg_seek_time", "name") = "Rotate speed, ms"
Set ^сatalog(root_id, sub2_id, "Properties", "avg_seek_time", "sort") = 3

Set ^сatalog(root_id, sub2_id, "goods", id_good3) = 1
Set ^сatalog(root_id, sub2_id, "goods", id_good4) = 1
 
상품을 보유한 전 세계 시장은 이렇게 보인다.

Set ^good(id_good, property1) = value1
Set ^good(id_good, property2) = value2
Set ^good(id_good, property3) = value3
Set ^good(id_good, "catalog") = catalog_id
 
물론 우리는 색인을 필요로 한다. 이렇게 하면 상품 목록의 어떤 부분에도 필요한 속성에 따라 정렬할 수 있다.글로벌 인덱스의 구조는 다음과 같습니다.

Set ^index(id_catalog, property1, id_good) = 1
; To quickly get the full path to concrete sub-catalog
Set ^index("path", id_catalog) = "^catalog(root_id, sub1_id)"
 
따라서 디렉터리의 어떤 부분에서든 우리는 정렬 목록을 얻을 수 있다.전역 인덱스는 선택할 수 있습니다.목록에 있는 이 부분의 제품 수량이 매우 많을 때만 쓸모가 있다.

프리젠테이션 데이터 처리를 위한 ObjectScript 코드


이제 ObjectScript를 사용하여 데이터를 처리합니다.우선 특정 상품의 특성을 알아보자.우리는 특정 상품의 ID를 가지고 있으며, 정렬 값에 따라 그 속성을 표시해야 한다.다음은 코드입니다.
get_sorted_properties(path, boolTable)
{
  ; remember all the properties in the temporary global
  While $QLENGTH(@path) > 0 {
    if ($DATA(@path("Properties"))) {
      set ln=""
      for {
        Set ln = $order(@path("Properties", ln))
        Quit: ln = ""

        IF boolTable & @path("Properties", ln, "table_view") = 1 {
          Set ^tmp(@path("Properties", ln, "sort"), ln) = @path("Properties", ln, "name")
        }
      ELSE {
        Set ^tmp(@path("Properties", ln, "sort"), ln) = @path("Properties", ln, "name")
      }
    }
  }
}

print_sorted_properties_of_good(id_good)
{
  Set id_catalog = ^good(id_good, "catalog")
  Set path = ^index("path", id_catalog)

  Do get_sorted_properties(path, 0)

  set ln =""
  for {
   Set ln = $order(^tmp(ln))
   Quit: ln = ""
   Set fn = ""
   for {
    Set fn = $order(^tmp(ln, fn))
    Quit: fn = ""
    Write ^tmp(ln, fn), " ", ^good(id_good, fn),!
   }
  }
}
 
다음은 목록 섹션에서 id_catalog 기반 제품을 표 형식으로 가져오고자 합니다.
 
print_goods_table_of_catalog(id_catalog)
{ 
  Set path = ^index("path", id_catalog)
  Do get_sorted_properties(path, 1)

  set id=""
  for {
    Set id = $order(@path("goods"), id)
    Quit: id = ""

    Write id," ", ^good(id, "price"), " "

    set ln =""
    for {
      Set ln = $order(^tmp(ln))
      Quit: ln = ""
      Set fn = ""
      for {
        Set fn = $order(^tmp(ln, fn))
        Quit: fn = ""
        Write ^tmp(ln, fn), " ", ^good(id, fn)
      }
      Write !
    }
  }
}
 

가독성: EAV SQL 및 글로벌


이제 EAV와 SQL의 사용과 글로벌스의 사용을 비교해 봅시다.코드의 선명도에 관해서는 이것이 주관적인 매개 변수임이 분명하다.예를 들어 신제품을 만드는 것을 봅시다.
EAV 방법부터 시작하여 SQL을 사용하겠습니다.우선, 우리는 대상 속성 목록을 얻어야 한다.이것은 독립된 임무로 상당히 시간을 소모한다.만약 우리가 이미 이 세 가지 속성의 ID를 알고 있다면: capacity, weightendurance이다.
START TRANSACTION
INSERT INTO good (name, price, item_count, catalog_id) VALUES ('F320 3.2TB AIC SSD', 700, 10, 15);

SET @last_id = LAST_INSERT_ID ();

INSERT INTO NumberValues ​​Values​​(@last_id, @id_capacity, 3200);
INSERT INTO NumberValues ​​Values​​(@last_id, @id_weight, 0.4);
INSERT INTO NumberValues ​​Values​​(@last_id, @id_endurance, 29000);
COMMIT
 
이 예에서 우리는 단지 세 가지 속성만 있기 때문에 이 예는 보기에 결코 무섭지 않다.일반적으로 트랜잭션 내의 텍스트 테이블에는 다음과 같은 항목이 삽입되어 있습니다.
 
INSERT INTO TextValues ​​Values​​(@last_id, @ id_text_prop1, 'Text value of property 1');
INSERT INTO TextValues ​​Values​​(@last_id, @ id_text_prop2, 'Text value of property 2');
...
INSERT INTO TextValues Values (@last_id, @id_text_propN, 'Text value of property N');
 
물론 ID 속성이 아닌 텍스트 기호, 예를 들어 숫자가 아닌'용량'을 사용한다면 SQL 버전을 조금 간소화할 수 있습니다.하지만 SQL 세계에서는 받아들일 수 없다.일반적으로 숫자 ID를 사용하여 솔리드 인스턴스를 열거합니다.따라서 인덱싱 속도가 빨라지고(더 적은 바이트 필요) 고유성을 추적할 수 있으며 새 ID를 자동으로 생성할 수 있습니다. 이 경우 삽입된 세그먼트는 다음과 같습니다.
 
INSERT INTO NumberValues ​​Values​​(@last_id, 'capacity', 3200);
INSERT INTO NumberValues ​​Values​​(@last_id, 'weight', 0.4);
INSERT INTO NumberValues ​​Values​​(@last_id, 'endurance', 29000);
 
다음은 글로벌스를 사용하는 것과 같은 예입니다.
 
TSTART
Set ^good(id, "name") = "F320 3.2TB AIC SSD"
Set ^("price") = 700, ^("item_count") = 10, ^("reserved_count") = 0, ^("catalog") = id_catalog
Set ^("capacity") = 3200, ^("weight") = 0.4, ^("endurance") = 29000
TCOMMIT
 
이제 EAV 방법을 사용하여 다음 사항을 제거합니다.
 
START TRANSACTION
DELETE FROM good WHERE id = @ good_id;
DELETE FROM NumberValues ​​WHERE good_id = @ good_id;
DELETE FROM TextValues ​​WHERE good_id = @ good_id;
COMMIT
 
그런 다음 글로벌스에 대해 같은 작업을 수행합니다.
 
Kill ^good(id_good)
우리는 또한 코드 길이 방면에서 이 두 가지 방법을 비교할 수 있다.앞의 예시에서 볼 수 있듯이 글로벌스를 사용할 때 코드가 더욱 짧다.이거 좋네.코드가 짧을수록 오류가 적고 이해하기 쉽고 유지하기 쉽다.
일반적으로 더 짧은 코드도 더 빠르다.이 예에서 이것은 당연히 정확하다. 왜냐하면 글로벌스는 관계표보다 낮은 수준의 데이터 구조이기 때문이다.

EAV 및 Globals를 사용한 데이터 크기 조정


다음은 수평 축소를 봅시다.EAV 방법을 사용하면 최소한 세 개의 가장 큰 테이블을 서버에 분배해야 합니다: Good,NumberValues,,​​및 텍스트 값입니다.실체와 속성을 가진 표는 정보가 거의 없기 때문에 모든 서버에 완전히 복사할 수 있다.
각 서버에서 수평 확장을 통해 다양한 제품은 Good, NumberValue,​​및 텍스트 값​​탁자.각 서버의 제품에 특정 ID 블록을 할당해야 서로 다른 제품의 ID가 중복되지 않습니다.
글로벌 수평 확장의 경우 글로벌 내에서 ID 범위를 구성하고 각 서버에 글로벌 범위를 할당해야 합니다.
EAV와 글로벌스의 복잡성은 대체적으로 같다. 단지 EAV 방법에 대해 우리는 세 개의 표에 ID 범위를 설정해야 한다.글로벌스를 사용하면 전역적으로 ID를 설정하기만 하면 됩니다.전체 국면의 수평 축소를 조직하기 쉽다는 것이다.

EAV 및 Globals 데이터 손실


마지막으로 데이터베이스 파일이 손상되어 데이터가 분실될 위험을 고려해 봅시다.모든 데이터를 다섯 개의 테이블에 저장하는 것이 더 쉽습니까? 아니면 세 개의 전역 테이블에 저장합니까? (전역 인덱스 포함)
나는 세 개의 공에서 더욱 쉽다고 생각한다.EAV 방법에서 서로 다른 상품의 데이터가 표에 혼합되고 글로벌스에 대한 정보의 저장은 더욱 전면적이다.밑바닥 지점은 순서대로 저장하고 정렬한다.따라서 EAV 방법의 어떤 표의 손상에 비해 일부 전역 데이터의 손상은 손상을 초래할 수 없으며, EAV 방법에서는 데이터가 교차하는 스파게티처럼 저장된다.
데이터 복구의 또 다른 골치 아픈 문제는 정보의 표시이다.EAV 방법에서 정보는 몇 개의 표로 나누어져 있으며, 특수한 스크립트가 그것을 하나의 전체로 조립해야 한다.글로벌의 경우 ZWRITE 명령만 사용하면 노드의 모든 값과 하위 브랜치를 표시할 수 있습니다.

InterSystems IRIS Globals: 더 나은 방법?


EAV 메서드는 계층형 데이터를 저장하는 기술이 되었습니다.시계는 처음에는 끼워 넣은 데이터를 저장하는 데 쓰이지 않았다.실제 EAV 방법은 테이블에서 글로벌 변수를 시뮬레이션하는 것입니다.테이블이 글로벌스보다 높은 수준, 느린 데이터 저장 구조임을 감안하면 글로벌스에 비해 EAV 방법은 실패했다.
내가 보기에 차원화된 데이터 구조에 대해 글로벌스는 프로그래밍에 있어 더욱 편리하고 이해하기 쉬우며 속도가 빠르다.
프로젝트에 대한 EAV 접근 방식을 계속 계획하고 있는 경우에는 계층형 데이터를 저장하기 위해 시스템 간 IRIS Global을 사용하는 것이 좋습니다.

좋은 웹페이지 즐겨찾기