Ubuntu 16.04 Python3 配置SQLite3 的 icu 分词

前言

最近在几台空机器上玩了玩DHT嗅探器。目前看还不错。

存储的Meta数据是使用SQLite3,语言是Python3 。原本一切都很完美,不过在存储了几十万的文件信息后,悲催的事情发生了:查询过慢…….

原本使用的查询方案是Query关键词Like,后来发现like的方案果真不是亲娘养的,太慢了。

match是个不错的方法,不过需要依赖虚拟表。虚拟表好说,一般python的内置sqlite3库已经支持,但是,其默认配置是无法支持中文的……

众所周知,中文才是采种子的关键啊,亲……

于是,需要配置icu方案。折腾了几小时后,大概总结如下:

环境安装

安装icu相关的库和工具:

1
2
sudo apt install icu-devtools
sudo apt install libicu-dev

下载sqlite3的源码

1
wget http://www.sqlite.org/2017/sqlite-autoconf-3210000.tar.gz

PS:这是3.21的代码,比较好用。

编译SQLite3

解压源码后,使用以下命令配置SQlite3的configure

1
CFLAGS='-O3 -DSQLITE_ENABLE_ICU' CPPFLAGS=`icu-config --cppflags` LDFLAGS=`icu-config --ldflags` ./configure --enable-readline --enable-fts5

开工

1
make

挣扎一番,编译出来的库放置在代码路径的.libs下。拷贝到某个目录。我这里是:/opt/3rd/sqlite3/libs

1
cp .libs /opt/3rd/sqlite3/libs -R

配置Python环境

肯定是使用virtualenv的。

1
2
virtualenv -p python3 venv
source venv/bin/activate

然后,进入Python REPL,看看sqlite3的版本

1
2
3
4
5
6
>>> import _sqlite3
>>> _sqlite3.__file__
'/usr/lib/python3.5/lib-dynload/_sqlite3.cpython-35m-x86_64-linux-gnu.so'
>>> import sqlite3
>>> sqlite3.sqlite_version
'3.11.0'

ldd下sqlite3的库文件

1
2
3
4
5
6
7
$ ldd /usr/lib/python3.5/lib-dynload/_sqlite3.cpython-35m-x86_64-linux-gnu.so
linux-vdso.so.1 => (0x00007fff98d84000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f135f60a000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f135f241000)
libsqlite3.so.0 => /usr/lib/x86_64-linux-gnu/libsqlite3.so.0 (0x00007f135ef6b000) <----这行,目前使用系统库
/lib64/ld-linux-x86-64.so.2 (0x000055ef9f996000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f135ed67000)

然后,将我们刚编译出来的sqlite3替换下系统库

1
export LD_LIBRARY_PATH=/opt/3rd/sqlite3/libs

再ldd下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$ ldd /usr/lib/python3.5/lib-dynload/_sqlite3.cpython-35m-x86_64-linux-gnu.so
linux-vdso.so.1 => (0x00007ffe405ec000)
libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f81f9ecf000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f81f9b06000)
libsqlite3.so.0 => /opt/3rd/sqlite3/libs/libsqlite3.so.0 (0x00007f81f97d3000)
^ 这个替换了,而且多了很多icu相关的so依赖
/lib64/ld-linux-x86-64.so.2 (0x0000563243794000)
libicui18n.so.55 => /usr/lib/x86_64-linux-gnu/libicui18n.so.55 (0x00007f81f9371000)
libicuuc.so.55 => /usr/lib/x86_64-linux-gnu/libicuuc.so.55 (0x00007f81f8fdd000)
libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f81f8cd3000)
libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f81f8acf000)
libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f81f874d000)
libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f81f8536000)
libicudata.so.55 => /usr/lib/x86_64-linux-gnu/libicudata.so.55 (0x00007f81f6a7f000)

目前应该OK了,在python环境里面测试下:

1
2
3
4
5
6
>>> import _sqlite3
>>> _sqlite3.__file__
'/srv/magnetico/venv/lib/python3.5/lib-dynload/_sqlite3.cpython-35m-x86_64-linux-gnu.so'
>>> import sqlite3
>>> sqlite3.sqlite_version
'3.21.0'

版本已经升级~

搞定收工。

PS,如果想长期替换,则在venv/bin/activate里面添加:

1
export LD_LIBRARY_PATH=/opt/3rd/sqlite3/libs