Solr란?
: 검색 엔진 솔루션
: 인덱스를 만들어서 빠른 검색이 가능하도록 한다.
어떤 식으로 빠르게 하지?
Inverted Index 를 통해서!
Inverted Index란, 다음과 같이 ID와 Tags의 순서가 inverted된 구조의 인덱스!
전통적 방식의 DB 또는 데이터 스토리지 | → | Inverted Index | ||
ID | Tags | Tags | ID | |
1 | banana | banana | 1, 3 | |
2 | market | market | 2 | |
3 | delicious banana | declious | 3,4 | |
4 | delicious | - |
Solr가 사용하는 검색 알고리즘: TF-IDF
TF : Term Frequency
검색 키워드를 더 많이 포함하는 검색결과(Document)가 더 높은 점수를 득점하는 알고리즘. (이 득점에 의해 검색결과 관련도가 높아진다.)
IDF : Inverse Document Frequency
키워드를 포함하는 검색 결과에서 공통된 단어를 많이 포함할수록 저득점하는 알고리즘.
예)
Senior Solr Engineer 의 경우, 'Senior'와 'Engineer'는 여러 도큐멘트에서 발견될 확률이 높기 때문에 이 단어 반복해서 많이 들어가는 도큐멘트일수록 저득점하게 된다. 결과적으로 다른 도큐멘트에서 'Solr' 라는 단어가 포함되어있지 않다는 전제하에 'Solr'를 포함하는 도큐멘트가 높은 점수를 받게 된다. 다른 예로는 'a, the.. etc'
Solr는 TF와 IDF가 균형을 이루면서 신뢰성 높은 검색결과를 도출할 수 있도록 한다.
Solr를 사용해야하는 이유
예를 들어서, 'a senior solr engineer' 를 전통적인 데이터베이스 쿼리로 검색하려면 어떻게 해야할까?
# 검색결과가 별로 없음.
SELECT * FROM <TABLE>
WHERE title LIKE 'a'
AND title LIKE 'senior'
AND title LIKE 'solr'
AND title LIKE 'engineer';
# 관계없는 검색결과가 많아짐.
SELECT * FROM <TABLE>
WHERE title LIKE 'a'
OR title LIKE 'senior'
OR title LIKE 'solr'
OR title LIKE 'engineer';
위와 같은 방식은 결과에 신뢰성이 없다!
왜냐하면, 'a, senior, solr' 와는 전혀 관계없고, 'engineer' 만 포함되는 도큐멘트가 포함될 수 있기 때문.
자세히 설명하면, 찾고자하는건 solr 엔지니어이지만, 전기 엔지니어에 관련된 검색결과가 나올 수 있다는 것!
이런식의 전통적인 방식의 문제점은 이것말고도 많이 있다.
- 특정 substring만이 검색 대상이 됨
- '산다', '사다' 와 같은 언어적인 변화에 대응 불가
- '사다', '구매하다' 와 같은 동의어 구분 불가
- 중요하지 않은 단어가 포함 됨 (예로 들면 'a senior solr engineer'의 'a')
- 상관없는 검색결과가 포함
- 검색 연관 순위 판단 불가
그럼 Solr는 어떤 장점이?
- 동의어 판단 가능
- 불필요한 단어 무시 가능
- 각 검색결과 우선순위 판단 가능
오케이. 그럼 언제 Solr를 사용해야 할까?
Solr 에는 5가지 특징이 있다.
- Text-centric : Text가 중심이 되는 검색일 때 효과적이다. 예를 들어 검색의 중요한 요소가 Text가 아닌 Date라면 Solr를 사용하는 이점이 없다.
- Read-dominant : Read 작업이 Write 작업보다 더 많은 비중을 차지해야한다. Writing이 더 많이 발생하는 경우라면 다른 NoSQL(Cassandra 등등)이 더 적합하다.
- Documented-oriented : XML, JSON 등등의 형식화된 데이터
- Large amount of data : 데이터의 용도가 검색 또는 display가 아니라면 Solr를 사용할 이유가 없다.
- Flexible schema : 획일화된 데이터가 아닌 유연성 있는 랜덤한 데이터인 경우에도 Solr는 대응이 가능하다.
Solr Core 란?
하나의 물리적인 인덱스!
Solr Collection 이란?
Solr는 하나의 인덱스를 클러스터에 존재하는 여러 서버에 저장하는데 이 클러스터를 Collection이라고 부르는 듯?
아직은 확실하지 않으니 TBD!
Solr 연습 세팅하기
1. Solr Core 생성하기
<Solr directory>/server/solr/configsets/sample_techproducts_configs 를 instanceDir 로 설정해서 name은 자유롭게 설정한 후 생성!
2. Solr 더미 데이터 입력하기
cd <solr path>/example/exampledocs
java -jar -Dc=<core name> post.jar *.xml
Query Basics
- qt (Query Type) : /select or /update ...
- q (Query) : <field name>:<search value>
- q 파라미터의 결과물은 연관도가 높은 순으로 정렬되어서 리턴된다!
- q.op (Query Operator): AND, OR 연산자 설정
- fq (Filter Query) : q 파라미터와 같은 방식으로 사용. <field name>:<search value>
- q 파라미터와 다른 점은 이 쿼리의 결과는 연관도 정렬순이 아니라는 것
- 캐시가 동작하는 것! (이로 인해 쿼리가 빨라질 수 있음.)
- sort : 정렬순을 정한다. ex) <field name> <asc OR desc>
- start, rows :
- start : start 페이지를 설정
- rows : 한 페이지당 보여지는 row 수를 설정
- fl (field list) : 쿼리 결과에 포함할 필드를 설정한다. ex) <field name1>,<field name2>,<so on..>
- score 필드와 같이 숨겨져있는 필드도 확인 가능하다. (score는 TF-IDF 의 점수!)
- df (default search field) : 디폴트 서치 필드를 설정. 예를 들어, q 파라미터에 서치 필드를 설정하지 않았을 때 df 값이 디폴트로 사용된다.
- wt (writer type) : 쿼리 결과의 포맷을 설정. xml, json..
Solr Query URL 구조
http://domain:port/solr/<solr core name>/<query type>?df=..&q=..
디폴트 row 개수만큼 결과를 반환하기 때문에 (10 rows), 더 많은 결과를 위해서는 rows 설정을 바꾸면 된다! ex) rows=20
Solr는 인덱스를 할 때 schema(managed-schema) 에 정의된 대로 데이터를 필터해서 저장한다.
그러면 스키마 디자인은 어떤 식으로 해야할까?
- 인덱싱을 위한 도큐먼트는 어떤 식으로 정의해야 할까?
: 쿼리 유저의 관심사에 따라 정의해야한다.
: 스키마 설정을 수동으로 안 해도 solr가 입력되는 도큐먼트를 보고 자동으로 스키마를 변경하기는 한다. 하지만 역시나 수동으로 하는게 개발자가 원하는 동작을 안전하게 구현하는 방법!- 예를 들면, 수동 설정을 통해서만 도큐먼트 A, B가 각각 solr, SOLR를 입력하더라도 lowercase해서 동일한 인덱스로 처리하도록 만든다 등등의 설정을 스키마를 통해 할 수 있다.
- 각각의 도큐먼트는 어떻게 구별될까? (인덱스로써의 유니크한 구분 방법)
: ID를 통해. ID를 지정하지 않아도 solr 내부적으로 생성하도록 되어 있음.
: 혹시 유니크한 필드를 id가 아닌 다른 필드명으로 하고 싶을 때에도 설정이 가능한데, 이 변경은 수동으로만 변경할 수 있다. - 도큐먼트의 어떤 필드를 유저가 검색 가능하도록 해야할까?
: 쿼리 유저가 가장 많이 사용하는 필드 위주로!
: 그리고, 쿼리 조건으로 사용할 필드를 인덱스 해야한다. ex) order by, group by, etc..
: 즉, 검색 조건으로써 사용 가능하게 하려면 인덱싱 할 필요가 있다. - 도큐먼트의 어떤 필드를 유저의 검색결과에 포함시켜야할까?
: stored 필드를 이용해서 검색 결과에 포함시킬지를 설정. 유저에게 공개할 필요가 없는 필드는 false를 명시적으로 설정할 필요가 있다.
※ stored vs. docValues
stored 필드는 Row-oriented이고, docValues는 Column-oriented다.
sort, group by 등을 할 때에는 docValues가 true인 필드를 사용하는 것이 성능적으로 좋다.
자세한 내용은 TBD..
스키마 변경은 Schema API를 통해서(HTTP) : 공식문서
수동으로 managed-schema 파일을 변경하는 것보다, schema API를 통하면 다음과 같은 장점이 있다.
- 스키마 변경 후 core의 reload && restart 등의 작업에 대해 신경 쓸 필요가 없다. Schema API가 알아서 해주니까.
- 변경할 스키마에 에러가 없는지 validation 기능을 가지고 있다.
중요한 포인트!
Schema를 변경하더라도 이전에 이미 인덱싱된 도큐먼트에 대해서는 변경이 일어나지 않는다.
즉, 변경 후 새롭게 인덱싱되는 도큐먼트에 한해서 변경된 스키마가 적용됨.
그렇기 때문에 스키마를 변경한 후에는 이전에 인덱싱된 도큐먼트들을 reindexing해야만 한다. 아니면 데이터에 접근이 불가할 수 있음.
기타 필드들..
MultiValued 필드
: 동일한 필드명에 여러 값이 들어갈수있도록 할 때 사용
자주 사용되는 리퀘스트
- Adds
- Deletes
- Updates
: id 필드를 통해 변경할 도큐먼트 지정하기! 안하면 무서운 일이 일어난다.
: 도큐먼트의 version 번호를 지정함으로써 도큐먼트의 Concurrency를 보장할 수 있다. - Commits
- Optimizations