Sphinx 검색엔진 2부 - 설정 및 사용




설정



이전 글에서 Sphinx 설치와 설정 방법에 대해서 알아보았습니다.

이번에는 어떻게 사용할 수 있는지에 대해서 알아보도록 하겠습니다.


현재 제 Database 의 설정은 다음과 같습니다. 이전에 포스팅 할 당시와 좀 다르다는 점 먼저 말씀드립니다.

(서버가 변경되었습니다 ㅎ)



Database Table 의 구조

mysql> desc words_kr;

+-------+------------------+------+-----+---------+----------------+

| Field | Type             | Null | Key | Default | Extra          |

+-------+------------------+------+-----+---------+----------------+

| id    | int(11) unsigned | NO   | PRI | NULL    | auto_increment |

| word  | varchar(32)      | NO   | MUL | NULL    |                |

+-------+------------------+------+-----+---------+----------------+

2 rows in set (0.01 sec)



Table 의 Records

mysql> select * from words_kr limit 5;

+----+-----------+

| id | word      |

+----+-----------+

|  1 | 사람      |

|  2 | 소망      |

|  3 | 인력      |

|  4 | 소나기    |

|  5 | 바람      |

+----+-----------+

5 rows in set (0.00 sec)




Sphinx.conf 파일

source words_kr

{

    type            = mysql


    sql_host        = localhost

    sql_user        = und3r

    sql_pass        = my_password

    sql_db          = und3r

    sql_port        = 3306  # optional, default is 3306

    sql_query_pre   = SET NAMES UTF8


    sql_query       = SELECT id, word FROM words_kr

    sql_field_string= word

}



index words_kr

{

    source          = words_kr

    path            = /var/lib/sphinx/words_kr

}



indexer

{

    mem_limit       = 128M

}



searchd

{

    listen          = 9312

    listen          = 9306:mysql41

    log         = /var/log/sphinx/searchd.log

    query_log       = /var/log/sphinx/query.log

    read_timeout    = 5

    max_children    = 30

    pid_file        = /var/run/sphinx/searchd.pid

    seamless_rotate = 1

    preopen_indexes = 1

    unlink_old      = 1

    workers         = threads # for RT to work

    binlog_path     = /var/lib/sphinx/

}



만약 Database 의 password 에 특수문자가 포함되어 있다면, escape 해 주어야 합니다. 예를들어 password 가 'und3r#' 이라면, 아래처럼 되어야 합니다.

sql_pass = und3r\#


유니코드를 제대로 출력하기 위해서는 "sql_query_pre   = SET NAMES UTF8" 부분을 반드시 넣어 주어야 합니다. :)


위 설정이 가장 기본적인 형태입니다. 사실 여기서 한글이나 일본어, 중국어 같은 문자로 검색을 하려면 설정을 조금 해 주어야 합니다. 이 부분은 밑에서 다시 설명 드리도록 하겠습니다. :)





실행



자, 이제 모든 설정은 끝이 났습니다. 이제 무엇을 해야 할까요?

동작 원리를 생각해 봅시다.


1. Sphinx 는 Database 에 접속해서 데이터를 긁어 옵니다.

2. Sphinx 는 긁어온 데이터로 index 트리를 생성합니다.

3. Sphinx 는 사용자로부터 요청이 오면, 응답을 해 주어야 합니다.

4. RT 를 사용하지 않는 이상, 주기적으로 Database 의 record 를 update 해야 합니다.


이 정도가 되겠네요.


현재 우리가 진행한 작업은 Database 에 접속하는 정도(?) 라고 볼 수 있겠네요.

그럼 이제 데이터를 긁어와 보도록 하겠습니다.


indexer 구성

[und3r@sungwook ~]$ sudo /usr/bin/indexer -c /etc/sphinx/sphinx.conf --all

[sudo] password for und3r:

Sphinx 2.2.8-id64-release (rel22-r4942)

Copyright (c) 2001-2015, Andrew Aksyonoff

Copyright (c) 2008-2015, Sphinx Technologies Inc (http://sphinxsearch.com)


using config file '/etc/sphinx/sphinx.conf'...

indexing index 'words_kr'...

collected 58 docs, 0.0 MB

sorted 0.0 Mhits, 100.0% done

total 58 docs, 131 bytes

total 0.003 sec, 37654 bytes/sec, 16671.45 docs/sec

total 64 reads, 0.000 sec, 0.0 kb/call avg, 0.0 msec/call avg

total 12 writes, 0.000 sec, 0.1 kb/call avg, 0.0 msec/call avg




indexer 를 이용하면 되는데, /usr/bin 에 있습니다. 그래서 절대경로를 적어줄 필요는 없는데, 확인차 붙여주었습니다 :)

-c 는 어떤 config 파일을 실행할 것인지에 대한 옵션입니다. 마지막으로 --all 은 모든 index 를 생성하겠다는 이야기입니다. 제 경우라면, sphinx.conf 파일 안에 words_kr 이라는 index 하나 밖에 없기 때문에, 결국 아래랑 동일합니다.


[und3r@sungwook ~]$ sudo indexer -c /etc/sphinx/sphinx.conf words_kr


만약 sphinx daemon 을 돌리고 있는 중이라면, --ratate 옵션 함께 주어야 합니다. 이후 설명 드리겠습니다.



자, 이제 제대로 data 가 들어왔는지 확인해 보도록 하겠습니다. sphinx 는 mysq client 로 접근하면 확인이 가능합니다.

그런데 접속을 하려면, sphinx server 가 돌고 있어야 하지 않겠습니까?


위에 indexer 는 말 그대로, database 파일을 긁어온게 전부입니다.(단순히 긁어온건 아니고, indexer 트리를 생성했죠)

서버는 돌려 봅시다. 서비스 하려면 서버가 필요합니다.


[und3r@sungwook ~]$ sudo searchd -c /etc/sphinx/sphinx.conf

Sphinx 2.2.8-id64-release (rel22-r4942)

Copyright (c) 2001-2015, Andrew Aksyonoff

Copyright (c) 2008-2015, Sphinx Technologies Inc (http://sphinxsearch.com)


using config file '/etc/sphinx/sphinx.conf'...

listening on all interfaces, port=9312

listening on all interfaces, port=9306

precaching index 'words_kr'

precached 1 indexes in 0.001 sec


-c 옵션은 indexer 랑 동일하게 config 파일을 지정해 주는 것입니다.


프로세스를 확인해 보죠.

[und3r@sungwook ~]$ ps aux | grep searchd

root      3163  0.0  0.0  92680  1652 ?        S    15:32   0:00 searchd -c /etc/sphinx/sphinx.conf

root      3164  0.1  0.2 102136  5068 ?        Sl   15:32   0:00 searchd -c /etc/sphinx/sphinx.conf



이제 접속해 보도록 합시다.

[und3r@sungwook ~]$ mysql -h0 -P9306

Welcome to the MySQL monitor.  Commands end with ; or \g.

Your MySQL connection id is 1

Server version: 2.2.8-id64-release (rel22-r4942)


Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.


Oracle is a registered trademark of Oracle Corporation and/or its

affiliates. Other names may be trademarks of their respective

owners.


Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.


mysql>


host 는 0 으로 주고, 포트는 sphinx.conf 파일에서 설정한 9306 으로 접속합니다.


데이터를 확인해 봅시다.

mysql> show tables;

+----------+-------+

| Index    | Type  |

+----------+-------+

| words_kr | local |

+----------+-------+

1 row in set (0.00 sec)


mysql> desc words_kr;

+-------+--------+

| Field | Type   |

+-------+--------+

| id    | bigint |

| word  | field  |

| word  | string |

+-------+--------+

3 rows in set (0.00 sec)


mysql> select * from words_kr limit 5;

+------+-----------+

| id   | word      |

+------+-----------+

|    1 | 사람      |

|    2 | 소망      |

|    3 | 인력      |

|    4 | 소나기    |

|    5 | 바람      |

+------+-----------+

5 rows in set (0.00 sec)


눈치 채셨겠지만, sphinx 에서는 database 를 select 하는게 없습니다. 이미 설정 되어있다고 생각하시면 됩니다. table 을 확인해보니, conf 파일에서 설정한 index 가 있네요. :)


주의할 점은 select 문 사용시, sphinx 에서는 기본값으로 LIMIT 20 이 생략되어 있다고 보시면 됩니다. 실제 데이터가 20개 이상 있다고 하더라도, SELECT * FROM words_kr; 을 실행하면, 20개만 나옵니다. 전체를 출력하고 싶다면 COUNT(*) 로 RECORD 갯수를 읽어와서, select 하는 수 밖에 없는것 같습니다.



이제 모든 기본적인 사용은 끝이 났습니다. 그런데 지금 한 것은 최초 indexer 를 생성해서 그것을 사용할 뿐입니다.

주기적으로 변경된 data 를 database 로 부터 읽어와서 갱신해 주어야 합니다.


앞서 포스팅했듯이, rt 는 다른 database 에서 값을 읽어오는게 아니라, 자신이 database 이므로 이 문제가 없습니다. 반면 merge 나 위에 코드처럼 타 database 의 값을 읽어와서 활용하는 경우는 이야기가 다르죠.


이를 해결하기 위해서 linux 의 cron 을 많이 이용합니다.


먼저 indexer 를 update 하는 스크립트를 작성합니다. x 퍼미션 주는것 잊지 않도록 합니다. :)


[words_kr_updater.sh]

#!/bin/bash

/usr/bin/indexer --config /etc/sphinx/sphinx.conf --rotate words_kr


그리고 cron 에 등록해 줍니다. 전 그냥 root 의 crontab 에 넣어주었습니다. sphinx.conf 에 각종 값들 수정이 귀찮아서;;

[und3r@sungwook ~]$ sudo crontab -e


에디터가 열리면, 아래처럼 indexer 를 update 하는 스크립트를 등록해 줍니다.

5 * * * * /home/und3r/sphinx/words_kr_updater.sh


위 경우 5분에 한번씩 갱신하도록 되어 있는데, 시간설정 관련된 것은 cron 사용법을 참고하시기 바랍니다.

더불어 찝찝하면, 아래처럼 crontab 을 재시작 해 줍니다 ^^

[und3r@sungwook ~]$ sudo /etc/init.d/crond restart




이제 시스템이 주기적으로(위 경우 5분) Database 에서 새로운 record 들을 읽어와서 index 를 생성하게 되었습니다. 검색이나 복잡한 query 를 sphinx 에서 처리할 수 있게 된 것이죠.


마지막으로 다음 포스팅에서는 한글 관련된 부분과 검색관련된 부분에 대해서 알아보도록 하겠습니다.