1. Psql 安裝 (CentOS-7.x)
采用yum安裝psql是最簡潔高效的
# 更新一下yum
yum update -y
# 直接安裝
yum install postgresql-server -y
# 初始化數(shù)據(jù)庫
postgresql-setup initdb
# 加入linux的服務(wù)管理
systemctl enable postgresql.service
# 啟動(dòng)服務(wù)
systemctl start postgresql.service
安裝完成之后,我們可能需要配置一下,Psql有兩個(gè)配置文件
/var/lib/pgsql/data/postgres.conf
如果你需要遠(yuǎn)程訪問,請(qǐng)取消注釋,并吧localhost改成*,我本地安裝,只為了自己平時(shí)使用,所以我就默認(rèn)監(jiān)聽localhost就可以了

/var/lib/pgsql/data/pg_hba.conf
Psql 初始化過后,默認(rèn)提供一個(gè)postgres用戶和一個(gè)postgres數(shù)據(jù)庫,但是我們直接psql -U postgres -d postgres命令是連接不上的,因?yàn)樵谀J(rèn)配置里,當(dāng)前登錄的賬戶必須是postgres,才能連接
所以我們改一改,認(rèn)證方式改成md5或者password(不建議),默認(rèn)是沒有密碼的,所以要輸入密碼的時(shí)候,回車就好了
更粗暴的方式是直接把認(rèn)證方式改為trust,這樣凡是登錄到這臺(tái)電腦的用戶都被信任,個(gè)人電腦可以這么干了
更詳細(xì)的配置可以去看看官方文檔

這個(gè)時(shí)候,我們重啟服務(wù),就可以登錄了
systemctl restart postgresql.service
psql -U postgres -h localhost -w
2. Psql 關(guān)于全文檢索的支持(tsvector和tsquery)
個(gè)人覺得,Psql對(duì)全文檢索還是很友好了,以前還是通過Apache Lucene實(shí)現(xiàn)的,最近看看Psql,簡單了不少
Psql 提供兩個(gè)數(shù)據(jù)類型tsvector,tsquery,并且通過動(dòng)態(tài)檢索自然語言文檔的集合,定位到最匹配的查詢結(jié)果
一個(gè)
tsvector的值是唯一分詞的分類列表,把一話一句詞格式化為不同的詞條,在進(jìn)行分詞處理的時(shí)候,tsvector會(huì)自動(dòng)去掉分詞中重復(fù)的詞條,按照一定的順序裝入,例如
# psql的自動(dòng)分詞(默認(rèn)是英文分詞,中文分詞后面講)
select 'hello world'::tsvector;
# 輸出
tsvector
-----------------------------
'hello' 'world'
# 可以設(shè)置詞條位置常量
select 'hello:3 world:1'::tsvector;
# 輸出
tsvector
-----------------------------
'hello':3 'world':1
這個(gè)位置信息通常就是當(dāng)前文檔中單詞所處的位置,這個(gè)位置信息用于關(guān)注度的體現(xiàn)。位置信息常量的值的范圍為1 到 16383。分詞后,會(huì)把相同詞條的位置記錄到一個(gè)詞條中
tsquery,相當(dāng)于是查詢tsvector的查詢條件,并且可以聯(lián)合使用boolean 操作符來連接, & (AND), | (OR), and ! (NOT). 使用括號(hào)(),可以強(qiáng)制分為一組
在全文檢索的過程中,tsquery與tsvector之間采用@@操作符
select 'hello world fuck you hahahaha'::tsvector @@ 'hello & you'::tsquery;
?column?
------------------
t
對(duì)于英文全文檢索應(yīng)用來說,很多時(shí)候的句子是非標(biāo)準(zhǔn)化的,但是tsvector和tsquery是不會(huì)知道的,為處理加工的文本應(yīng)該通過使用
to_tsvector函數(shù)
# 采用psql提供的函數(shù)幫助我們將文本分詞
select to_tsvector('hello world');
to_tsvector
---------------------
'hello':1 'world':2
# 采用psql提供的函數(shù)進(jìn)行全文檢索
select to_tsvector('hello world fuck you hahah') @@ to_tsquery('hello & you');
?column?
------------------
t
在Psql中
@@操作符會(huì)將兩邊的文本進(jìn)行自動(dòng)的轉(zhuǎn)換
- tsvector @@ tsquery
- text @@ tsquery
- text @@ text
- 后兩種,text @@ tsquery 等同于 to_tsvector(x) @@ y.
- 而 text @@ text 等同于 to_tsvector(x) @@ plainto_tsquery(y).
plainto_tsquery() 用于將文本轉(zhuǎn)為tsquery,這樣就不用每次都去寫 & 條件了
3. Psql 索引類型
我們也要為全文檢索建立索引,提升查詢效率,我們?yōu)槿臋z索建立的索引是Gin索引
幾種基本索引類型
B-Tree
CREATE INDEX test1_id_index ON test1 (id);
B-Tree索引主要用于等于和范圍查詢,特別是當(dāng)索引列包含操作符" <、<=、=、>=和>"作為查詢條件時(shí),PostgreSQL的查詢規(guī)劃器都會(huì)考慮使用B-Tree索引。在使用BETWEEN、IN、IS NULL和IS NOT NULL的查詢中,PostgreSQL也可以使用B-Tree索引(MySQL則不會(huì))。然而對(duì)于基于模式匹配操作符的查詢,如LIKE、ILIKE、~和 ~*,僅當(dāng)模式存在一個(gè)常量,且該常量位于模式字符串的開頭時(shí),如col LIKE 'foo%'或col ~ '^foo',索引才會(huì)生效,否則將會(huì)執(zhí)行全表掃描,如:col LIKE '%bar'。
Hash
CREATE INDEX name ON table USING hash (column);
散列(Hash)索引只能處理簡單的等于比較。當(dāng)索引列使用等于操作符進(jìn)行比較時(shí),查詢規(guī)劃器會(huì)考慮使用散列索引。
這里需要額外說明的是,PostgreSQL散列索引的性能不比B-Tree索引強(qiáng),但是散列索引的尺寸和構(gòu)造時(shí)間則更差。另外,由于散列索引操作目前沒有記錄WAL日志,因此一旦發(fā)生了數(shù)據(jù)庫崩潰,我們將不得不用REINDEX重建散列索引。
GiST
CREATE INDEX name ON table USING gist (column);
GiST索引不是一種單獨(dú)的索引類型,而是一種架構(gòu),可以在該架構(gòu)上實(shí)現(xiàn)很多不同的索引策略。從而可以使GiST索引根據(jù)不同的索引策略,而使用特定的操作符類型。
GIN
CREATE INDEX name ON table USING gin (column);
GIN索引是反轉(zhuǎn)索引,它可以處理包含多個(gè)鍵的值(比如數(shù)組)。與GiST類似,GIN同樣支持用戶定義的索引策略,從而可以使GIN索引根據(jù)不同的索引策略,而使用特定的操作符類型。作為示例,PostgreSQL的標(biāo)準(zhǔn)發(fā)布中包含了用于一維數(shù)組的GIN操作符類型,如:<@、@>、=、&&等。
兩種建立索引方式
# 我新建一個(gè)posts表,記錄我的博客內(nèi)容,平時(shí)需要根據(jù)博客名和內(nèi)容做查詢
create table posts (
id integer,
title varchar(50) not null,
content text not null,
primary key(id)
);
- 為tsv函數(shù)建索引
create index post_tsvcontent_idx on posts using gin(to_tsvector('english', title || content));
- 新增一個(gè)tsv列,為列建立索引(推薦)
alter table posts add_column tsv_content tsvector;
update posts set tsv_content = to_tsvector('english', coalesce(title,'') || coalesce(content,''));
create index post_tsvcontent2_idx on posts using gin(tsv_content);
現(xiàn)在都可以對(duì)posts表里的內(nèi)容進(jìn)行全文檢索了
# 例如
select title from posts where to_tsvector(title || content) @@ plainto_tsquery('hello world');
# 或者
select title from posts where tsv_content @@ plainto_tsquery('hello world');
4. 用觸發(fā)器更新分詞字段
如果我們是單獨(dú)新建一列去存放tsvector的分詞內(nèi)容,為了簡便,我們希望在插入記錄過后,自動(dòng)對(duì)需要檢索的列生成分詞,所以我們就需要觸發(fā)器
# Psql 提供了兩個(gè)觸發(fā)器函數(shù)用于實(shí)現(xiàn)此功能
tsvector_update_trigger()
tsvector_update_trigger_column()
# 當(dāng)然,你也可以寫自己的觸發(fā)器
tsvector_update_trigger() 的使用
# 非常簡單
CREATE TRIGGER trigger_posts_tsv_content BEFORE INSERT OR UPDATE
ON posts FOR EACH ROW EXECUTE PROCEDURE
tsvector_update_trigger(tsv_content, 'english', title, content)
5. 采用zhparser支持中文分詞
zhparser是基于Simple Chinese Word Segmentation(SCWS)中文分詞庫實(shí)現(xiàn)的一個(gè)PG擴(kuò)展,作者是 amutu,源碼URL為https://github.com/amutu/zhparser
安裝SCWS
wget -q -O - http://www.xunsearch.com/scws/down/scws-1.2.2.tar.bz2 | tar xf -
cd scws-1.2.2
./configure
make install
安裝zhparser
git clone https://github.com/amutu/zhparser.git
cd zhparser
SCWS_HOME=/usr/local make && make install
配置zhparser擴(kuò)展
# 連接到目標(biāo)數(shù)據(jù)庫,創(chuàng)建zhparser解析器
create extension zhparser
# 將zhparser解析器作為全文檢索配置項(xiàng)
create text search configuration chinese (PARSER = zhparser);
然后通過\dF和\dFp命令查看配置

指定分詞策略
zhparser可以將中文切分成下面26種token
# 連接到目標(biāo)數(shù)據(jù)庫
select ts_token_type('zhparser');

普遍情況下,我們只需要按照名詞(n),動(dòng)詞(v),形容詞(a),成語(i),嘆詞(e)和習(xí)用語(l)6種方式對(duì)句子進(jìn)行劃分就可以了,詞典使用的是內(nèi)置的simple詞典,即僅做小寫轉(zhuǎn)換
所以添加如下映射
alter text search configuration chinese add mapping for n,v,a,i,e,l with simple;
最后效果
# 連接到目標(biāo)數(shù)據(jù)庫
select to_tsvector('chinese', '這周日你有空么');
# 輸出
to_tsvector
-------------------------
'么':2 '有空':1