为什么嗖嗖的提交如此缓慢

时间:2014-06-17 11:03:30

标签: python whoosh

我想知道为什么下面的代码让人感到有点慢。特别是提交需要相当长的时间。

我尝试使用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()

1 个答案:

答案 0 :(得分:1)

在提交中发生了某种类型的段合并;这也可以解释为什么procs=3会使事情变得更慢(合并更多的段!)。

对我来说,解决方案是按照建议的here设置multisegment=True

writer = ix.writer(procs=4, limitmb=256, multisegment=True)

您可以根据需要调整procslimitmb,但请注意 limitmb是按触发次数的!(即它们成倍增加)


注意事项:搜索速度会受到影响。例如:

  • 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,然后再次运行。

所以只是给一个大概的想法