我想知道为什么以下代码对whoosh有点慢。特别是提交需要相当长的时间。
我尝试使用writer的limitmb = 2048而不是默认值128,但是几乎没有区别。根据建议,我尝试使用procs = 3作为编写器,这会使索引编制更快一些,但提交速度甚至更慢。另外,由于索引为空,因此commit(merge = False)在这里没有帮助。
我得到这样的结果:
index_documents 12.41 seconds
commit 22.79 seconds
run 35.34 seconds
对于这么小的模式和大约45000个对象来说似乎有点多。
我使用whoosh 2.5.7和Python 2.7进行了测试。
这是正常的,我只是期望太多,还是我做错了什么?
我也进行了一些分析,似乎飞快地写着然后在阅读许多泡菜。这似乎与交易的处理方式有关。
from contextlib import contextmanager
from whoosh import fields
from whoosh.analysis import NgramWordAnalyzer
from whoosh.index import create_in
import functools
import itertools
import tempfile
import shutil
import time
def timecall(f):
@functools.wraps(f)
def wrapper(*args, **kw):
start = time.time()
result = f(*args, **kw)
end = time.time()
print "%s %.2f seconds" % (f.__name__, end - start)
return result
return wrapper
def schema():
return fields.Schema(
path=fields.ID(stored=True, unique=True),
text=fields.TEXT(analyzer=NgramWordAnalyzer(2, 4), stored=False, phrase=False))
@contextmanager
def create_index():
directory = tempfile.mkdtemp()
try:
yield create_in(directory, schema())
finally:
shutil.rmtree(directory)
def iter_documents():
for root in ('egg', 'ham', 'spam'):
for i in range(1000, 16000):
yield {
u"path": u"/%s/%s" % (root, i),
u"text": u"%s %s" % (root, i)}
@timecall
def index_documents(writer):
start = time.time()
counter = itertools.count()
for doc in iter_documents():
count = counter.next()
current = time.time()
if (current - start) > 1:
print count
start = current
writer.add_document(**doc)
@timecall
def commit(writer):
writer.commit()
@timecall
def run():
with create_index() as ix:
writer = ix.writer()
index_documents(writer)
commit(writer)
if __name__ == '__main__':
run()
在提交中发生了一些段合并;这也解释了为什么procs=3
使事情变得更慢(合并更多的段!)。
对我来说,解决方法是按照建议的multisegment=True
设置here。
writer = ix.writer(procs=4, limitmb=256, multisegment=True)
您可以根据需要调整procs
和limitmb
,但请考虑limitmb
是按进程计算的!(即它们成倍增加)]
Caveat:搜索速度会有损失。例如:
10000个文档:~200ms (w/o multisegment) vs 1.1secs (with multisegment)
50000个文档:~60ms (w/o multisegment) vs ~100ms (with multisegment)
仅在commit
上,我的系统的速度慢大约40%。我没有测量索引时间,但是multisegment
也更快。
这可能是原型解决方案。一旦知道了所需的Schema
和参数,便可以将multisegment
设置回False
,然后再次运行。
所以只是给一个大概的想法