생계/PostgreSQL2024. 10. 12. 15:11

GIN(Generalized Inverted Index) 인덱스란 ? 
PostgreSQL에서 복합적인 데이터를 효율적으로 검색하기 위해 사용되는 특수한 인덱스 유형
주요 특징은 아래와 같다. 

1. 복합 데이터 처리: 배열, JSON, hstore, tsvector 등 복합적인 데이터 타입에 적합
2. 키워드 기반 검색: 문서나 텍스트에서 특정 단어를 빠르게 찾을 수 있다.
3. 역인덱스 구조: 키워드나 토큰을 기반으로 데이터를 인덱싱
4. 전문 검색(Full-text search) 지원: 텍스트 검색 속도를 크게 향상
5. 다양한 연산자 지원: LIKE, ILIKE, ~, ~* 등 다양한 검색 연산자를 지원

GIN 인덱스는 특히 대량의 텍스트 데이터를 처리할 때 B-tree 인덱스보다 훨씬 효과적이며,
 검색 성능을 크게 향상시킬 수 있다.
  다만, 인덱스 생성과 업데이트에는 상대적으로 많은 시간이 소요될 수 있습니다

 

## 복합 데이터 처리

테스트 테이블을 만들고 GIN 인덱스 사용 전후의 플랜을 비교해보자 

-- Create a table with a JSONB column
CREATE TABLE products (
    id SERIAL PRIMARY KEY,
    name VARCHAR(100),
    details JSONB
);

-- Insert sample data
INSERT INTO products (name, details) VALUES
    ('Laptop', '{"brand": "TechCo", "specs": {"ram": "16GB", "storage": "512GB SSD"}, "tags": ["electronics", "computer"]}'),
    ('Smartphone', '{"brand": "Gadgetron", "specs": {"ram": "8GB", "storage": "256GB"}, "tags": ["electronics", "mobile"]}'),
    ('Headphones', '{"brand": "AudioPro", "specs": {"type": "over-ear", "wireless": true}, "tags": ["audio", "accessories"]}');


-- Query using the GIN index to find products with specific attributes
EXPLAIN ANALYZE
SELECT name, details
FROM products
WHERE details @> '{"brand": "TechCo"}';



-- Query to find products with specific tags
EXPLAIN ANALYZE
SELECT name, details
FROM products
WHERE details->'tags' @> '"electronics"'::jsonb;

 

-- Create a GIN index on the JSONB column
CREATE INDEX idx_product_details ON products USING GIN (details);

 

## 전문검색 처리 

 

-- 문서 테이블 생성 
CREATE TABLE  documents (
    id SERIAL PRIMARY KEY,
    content TEXT,
    content_tsv tsvector
);

-- 함수 생성: 랜덤 문장 생성
CREATE FUNCTION random_sentence() RETURNS TEXT AS $$
DECLARE
    words TEXT[] := ARRAY['PostgreSQL', 'database', 'index', 'query', 'performance', 'GIN', 'B-tree', 'full-text', 'search', 'optimization', 'SQL', 'data', 'management', 'system', 'relational', 'ACID', 'transaction', 'concurrency', 'scalability', 'replication'];
    sentence TEXT := '';
    word_count INT;
BEGIN
    word_count := 5 + random() * 10; -- 5에서 15 단어 사이의 문장 생성
    FOR i IN 1..word_count LOOP
        sentence := sentence || ' ' || words[1 + random() * (array_length(words, 1) - 1)];
    END LOOP;
    RETURN trim(sentence);
END;
$$
 LANGUAGE plpgsql;

-- 10,000개의 샘플 문서 생성
INSERT INTO documents (content, content_tsv)
SELECT 
    random_sentence(),
    to_tsvector('english', random_sentence())
FROM generate_series(1, 10000);

-- GIN 인덱스 생성 
CREATE INDEX  idx_gin_content ON documents USING gin(content_tsv);

-- 통계 업데이트
ANALYZE documents;

-- 검색 쿼리 실행 및 실행 계획 확인
EXPLAIN ANALYZE
SELECT id, content
FROM documents
WHERE content_tsv @@ to_tsquery('english', 'postgresql & index');

인덱스생성전

 

인덱스생성후

 

반응형
Posted by 돌고래트레이너
정보/생활정보2024. 9. 18. 22:29

과일을 먹을때마다 이것이 음식물 쓰레기인가 일반 쓰레기인가 기억이 안나서 매번 검색하고 했는데,

'매번 검색할거면 내 블로그에 올려서 내거에서 찾자' 란 마인드로 작성하는 글

 

바나나껍질 : 음식물 쓰레기

메론껍질 : 음식물 쓰레기

수박껍질 : 음식물 쓰레기

감자껍질 : 음식물 쓰레기

계란껍질 : 일반 쓰레기

닭 뼈 : 일반 쓰레기 

 

음식물 쓰레기인가 일반 쓰레기인가 구분하는 기준은 딱딱한것과 부드러운 것이라고 하는데 메론껍질은 딱딱해서 수긍이 잘안간다. 먹을수 있는 것이 음식물쓰레기라고 한다면 음쓰통에 쳐박혀 냄새나고 상한것을 아무리 동물이라도 먹인단 말인가? 여튼 기준은 납득되지 않지만 그냥 외운다

반응형
Posted by 돌고래트레이너
생계/MySQL2024. 9. 16. 15:14

mysql 은 replication 을 통해 복제서버를 사용할수 있게 해준다. 

복제서버는 백업이나 조회 용도로 쓸수 있어서 매우 유용하다. 

오라클은 ogg 를 사용하거나 data guard 를 사용해야하는데 라이센스를 추가로 구매해야 한다. 

그런면에서 mysql 은 참으로 혜자다. (오라클은 파티션도 EE 에서만 사용가능한데 mysql 은 무료다.)

 

MySQL Replication

mysql 이 제공하는 replication 은 데이터 변경을 기록하는 binlog 를 target db 에 전달하면 target 에서 relay log 라는 이름으로 기록하고 그것을 다시 target DB 에 반영하는 방식이다. 

그림출처 : https://avisheksharma.wordpress.com/2015/01/07/step-wise-guide-to-setup-mysql-replication/

 

이 구조에서의 특징은 아래와 같다. 

1. 소스와 타켓의 지연이 발생한다. 반영해야 할 변경량이 많을수록 지연은 커질수 있다. 완전 실시간 동기화를 요구하는 업무에는 맞지 않는다. 

2. 복제가 깨지기 쉽다.  오라클 RAC 처럼 shared storage 를 쓰는 경우 어느 인스턴스에서 접근해도 동일한 data 를 보장하지만, mysql 복제 방식은 각자 자기의 DB 를 가지고 사용하기에 동일한 DB임이 보장되지 않는다. 

실제로 mysql replication 구조를 운영환경에서 사용하는 중에 복제가 깨지는 일은 종종 일어난다. 

그렇지만 의도적으로 복제DB를 다른 형상으로 유지하고 싶은 경우도 있다. 인덱스를 다르게 유지하거나 스키마를 다르게 유지하는 등의 유연한 운영이 가능하다. 

 

AWS aurora mysql 

AWS 에서는 aurora 라고 부르는 DB cluster 를 통해 복제DB 를 제공한다. 

AWS 는 레거시 환경의 서버구조를 computing unit 과 storage 로 분리해서 제공하는데,

Aurora cluster 도 아래 그림처럼 sql, trasaction, caching 을 담당하는 instance 와  logging 과 storage 를 담당하는 shared storage volume 구조로 구성되어 있다. 

DB instance 는 writer (primary) instance 와 reader instance 의 두가지 타입으로 이루어져 있다. 

replication 과 다른 특이한 점은 writer 가 6개의 storage 에 write 를 하고 reader 에서는 자기의 storage 를 read만 할 뿐이다. 

출처: https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/Aurora.Overview.html

여기서 몇가지 의문점이 생길수 있다. 

Q1) 하나의 인스턴스에서 6개의 볼륨에 write 를 하는 것이 성능상 문제가 없는가? 

Q2) 클러스터를 유지하기 위해 6개의 스토리지 비용을 감당하는 것인가? 

그에대한 답은 아래와 같다. 

A1) write 명령에 대해서는 실제 data를 update 하는 것이 아닌 log record 만 우선 update 하는 방식으로 시간을 절약(궁극적으로는 당연히 모든 노드(6개)에서 page update를 한다)

A2) 모든 스토리지가 동일한 구성이 아니고 3개는 data 와 로그레코드를 가진 full segment, 3개는 로그레코드만 가진 tail segemnt 로 구성된다. 그래서 실제로 비용은 6배가 아닌 3.x 배 정도 소요된다. 

형상이 동일하게 유지되기 때문에 replication 방식처럼 의도적으로 다르게 형상을 관리하는 것이 불가능하다. 

RAC 와 replication  의 중간 정도 느낌이다.  

aurora cluster 가 6개의 storage 를 사용하는 이유는 어느하나가 일시적 장애를 만나도 서비스가 가능하게 만드려는데 목적이 있고 내부적으로는 quorum model 을 통해서 그것이 가능해진다. 이 내용은 별도의 포스팅에서 정리해보겠다.

 

반응형
Posted by 돌고래트레이너