유효한 SQL 인덱스 및 JSONB의 비규범화

최근에 내가 가장 좋아하는 데이터베이스 특성 중 하나는 PostgreSQL 중의 JSONB 데이터 형식이다.SQL과 NoSQL의 다툼을 살펴보려면:

  • SQL 클러스터 구성이 좋습니다!

  • NosQL 사람들의 구조가 좋지 않습니다!
  • PostgreSQL의 JSONB 데이터가 있으면 당신은 둘 다 잘할 수 있습니다.우리는 경직된 모델이 모든 유형의 데이터에 적합하지 않다는 것을 안다. 왜냐하면 모든 현실 세계의 데이터가 엄격한 형식을 따르는 것은 아니기 때문이다.예를 들어 로그 메시지, 오류, 코드 추적, JSON 웹 서비스는 서로 다른 데이터 족을 되돌려줍니다.그리고 데이터베이스에 이런 데이터를 저장하는 데는 좋은 용례가 많다.그러나 관계 기술은 매우 강력하다. 만약 약간의 비구조화된 데이터를 저장하기 위해 모든 것을 포기한다면 그것은 수치일 것이다.
    이 게시물에서 나는 네가 JSONB를 보러 가는 것을 건의할 뿐만 아니라너는 이미 이렇게 했을 것이다.저는 AppLand에서 사용하는 두 가지 기술을 추천하여 JSONB 데이터를 더욱 효과적으로 할 것입니다.시작하자.

    효율적인 JSONB 인덱스 조회
    SQL 데이터가 강력한 유형 열에 저장될 때 줄마다 통일된 구조가 있고 데이터 검색 효율이 높으며 인덱스도 쉽다는 것을 알고 있습니다.PostgreSQL은 또한 indexes on JSONB 열을 만들 수 있다는 사실을 모를 수도 있습니다.따라서 JSONB 문서에 name과 같은 공통 필드가 있으면 이 필드에 색인을 추가할 수 있습니다.그리고 JSONB에서 name을 효율적으로 검색할 수 있습니다. PostgreSQL은 모든 JSON을 검색해서 일치하는 이름을 찾을 필요가 없습니다.뿐만 아니라 당신은 JSON에서 name을 선택할 수 있습니다. PostgreSQL은 index-only scan이라는 기술로 JSON을 분석하지 않은 상태에서 이 데이터를 검색할 수 있습니다.

    효율적인 검색 – JSONB를 사용하여 생성된 열
    이제 JSONB 데이터의 하위 집합을 효율적으로 가져오고 모든 대상을 불러오고 해석하지 않으려면 어떻게 해야 합니까?AppLand에서는 데이터베이스에 AppMap data을 저장합니다.모든 AppMap에는 metadata이라는 강제 부분이 있는데 우리는 선택한 줄의 메타데이터를 효율적으로 추출하고 전체 JSONB열을 분석하지 않기를 희망한다(메타데이터는 보통 JSON 대상 총수의 1%에 미치지 않는다).놀랍게도 PostgreSQL 12 이후 PostgreSQL에는 generated columns이라는 기능이 있다.
    트리거를 사용한 적이 있다면, 한 줄을 삽입하거나 업데이트하거나 삭제할 때 데이터베이스에 데이터베이스 내 함수를 실행하도록 지시할 수 있습니다. 이 함수는 거의 무한한 방식으로 이 줄을 처리할 수 있습니다.생성된 열은 트리거와 같다.줄을 삽입하거나 업데이트할 때마다 자동으로 실행됩니다.생성된 열은 함수를 새 줄에 적용한 다음 그 함수의 결과를 줄에 저장합니다.
    따라서 생성된 함수를 사용하여 JSONB 열에서 공통 데이터를 추출하여 행에 저장할 수 있습니다.그런 다음 복제/캐시("비사양") 데이터에 액세스하기 위한 쿼리를 작성할 수 있습니다.그것은 정말 관계 세계와 비관계 세계 중 가장 좋다.

    하나의 예
    다음은 JSONB 인덱스와 열 생성의 구체적인 예입니다.이 예에 대해 나는 AppMap JSON을 사용할 것이다. 이것은 클래스 의존 관계도와 프로그램의 실행 추적을 나타낸다.최상위 수준에서 AppMap 형식은 metadata, classMapevents입니다.
    AppMap 데이터를 appmaps이라는 간단한 테이블에 저장하고 최소 기록을 추가합니다.
    CREATE TABLE appmaps (
        id uuid DEFAULT gen_random_uuid() PRIMARY KEY,
        data jsonb
    );
    -- data is schema-less so we can omit all fields except metadata
    INSERT INTO appmaps ( data )
    VALUES ( '{"metadata":{"name":"login"}}'::jsonb );
    
    인덱스를 사용한 최적화
    사용자가 이름별로 AppMap을 검색하려면 서버에서 data->'metadata'->>'name'을 검색해야 합니다.이중 화살표 ->>은 검색 조건이 일반 텍스트일 수 있도록 PostgreSQL에서 결과를 text(JSON에서 온 것)으로 변환하도록 지시합니다.
    CREATE INDEX idx_appmaps_name
    ON appmaps USING BTREE ((data->'metadata'->>'name'));
    
    주의: different types of indexes 사용 가능하며 장점도 있고 단점도 있습니다.BTREE은 텍스트에 적용됩니다.
    인덱스만으로 전체 질의를 수행하고 인덱스 검색만으로 다음을 수행할 수 있습니다.
    SELECT data->'metadata'->>'name' AS name
    FROM appmaps WHERE data->'metadata'->>'name' = 'login';
     name
    -------
     login
    (1 row)
    
    생성된 열을 사용하여 최적화
    만약 우리가 효과적으로 데이터 열에서 metadata을 꺼낼 수 있기를 희망한다면.GENERATED 열 추가:
    ALTER TABLE appmaps ADD COLUMN metadata JSONB
    GENERATED ALWAYS AS (data->'metadata') STORED;
    
    현재 모든 행은 metadata 열로 구성되어 있으며 이 열은 비규범화된 데이터를 저장합니다.
    SELECT id, metadata from appmaps;
                      id                  | metadata
    --------------------------------------+-------
     c5e4cfa5-1945-4685-a50f-7e5b0edd62e5 | {"name": "login"}
    (1 row)
    

    마무리
    이것은 우리가 App Land에서 사용하는 두 가지 기술이다. 우리가 JSON 데이터를'관계'로 표현하기를 원할 때 JSON 데이터를'관계'로 표현한다.PostgreSQL은 강력한 JSONB 데이터 유형을 제공할 뿐만 아니라 JSONB를 진정으로 유용하게 하는 단축키와 가용성 기교도 제공한다.
    네가 여기 있을 때
    우리는 지금 State of Software Architecture Quality을 조사하고 있다.우리의 목표는 300개의 회답을 얻는 것이다. 일단 우리가 목표에 도달하면, 우리는 코드를 작성한 여자 아이에게 1000달러를 기부할 것이다.설문지를 작성하여 우리가 소프트웨어 구조의 질을 이해하도록 도와주세요!물론 우리는 결과를 얻은 후에 총결산과 발표를 진행할 것이다.
    설문 조사를 작성하지 않으려는 경우 결과가 있을 때 공지를 받으려면 https://forms.gle/u8CPS3GGD6A7WHsG7을 작성하십시오.

    좋은 웹페이지 즐겨찾기