我有一个大约有1.2M名字的数据库。当您输入某人的姓名时,我正在使用Twitter的typeahead.js远程获取自动填充建议。在我的本地环境中,在您停止输入后显示结果大约需要1-2秒(在您键入时不显示自动完成),在Heroku上部署的应用程序上显示2-5 +秒(仅使用1个dyno) )。
我想知道在你停止输入之后它只显示建议的原因(以及延迟几秒)是因为我的代码没有得到优化吗?
页面上的脚本:
<script type="text/javascript">
$(document).ready(function() {
$("#navPersonSearch").typeahead({
name: 'people',
remote: 'name_autocomplete/?q=%QUERY'
})
.keydown(function(e) {
if (e.keyCode === 13) {
$("form").trigger('submit');
}
});
});
</script>
keydown片段是因为如果没有它,我的表单在推入时会因某些原因而无法提交。
我的django观点:
def name_autocomplete(request):
query = request.GET.get('q','')
if(len(query) > 0):
results = Person.objects.filter(short__istartswith=query)
result_list = []
for item in results:
result_list.append(item.short)
else:
result_list = []
response_text = json.dumps(result_list, separators=(',',':'))
return HttpResponse(response_text, content_type="application/json")
我的Person模型中的短字段也被编入索引。有没有办法改善我的先行者的表现?
答案 0 :(得分:3)
我不认为这与Django直接相关,但我可能错了。我可以为这种情况提供一些通用的建议:
(我的钱在#4或#5下面)。
1)从您的机器到Heroku的平均“ping”是多少?如果它很远,那就是额外的开销。但是并不多。当你指的是8-9秒时,肯定不会太多。注意,https
的惩罚会更大。
2)检查waitLimitFn
数据集中rateLimitWait
和remote
的值。它们是默认值吗?
3)在所有可能的情况下,问题是数据库/数据集相关。首先要检查的是建立与数据库的连接需要多长时间(您使用连接池吗?)。
4)第二件事:运行查询需要多长时间。我的赌注是在这一点或下一点。添加调试打印,或使用NewRelic(即使是免费计划也可以)。查看生成的查询并确保将其编入索引。让您的数据库“解释”此类查询的执行计划,并使其使用索引。
5)第三件事:结果大吗?例如,如果您指定“J”作为查询,我想会有很多答案。只是获取它们并将它们流式传输到客户端需要时间。在这种情况下:
5.1)为数据集指定minLength
。至少为3,如果不是4。
5.2)限制数据库查询返回的结果集。比如说,回报不超过10。
6)我不是Django专家,但要确保在Django中使用模型的方式不会使整个表首先加载到内存中。只是说'。
HTH。
答案 1 :(得分:1)
results = Person.objects.filter(short__istartswith=query)
result_list = []
for item in results:
result_list.append(item.short)
可能不是导致速度缓慢的唯一原因,但从性能的角度来看这可怕:从不循环遍历django查询集。要从django查询集中组合列表,您应该始终使用values_list。在这个具体案例中:
results = Person.objects.filter(short__istartswith=query)
result_list = results.values_list('short', flat=True)
通过这种方式,您可以直接从db获取单个字段,而不是:获取所有表行,从中创建Person实例,最后从中读取单个属性。
答案 2 :(得分:0)
Nitzan涵盖了许多可以提高性能的要点,但与他不同,我认为这可能与Django直接相关(至少在服务器方面)。
测试此方法的一种快速方法是更新name_autocomplete
方法,以便以Typeahead期望的格式返回10个随机生成的字符串。 (我们希望它们随机的原因是Typeahead的缓存不会扭曲任何结果)。
我怀疑您会看到Typeahead现在运行得非常快,您应该在键入minLength
字符串后立即看到结果。
如果是这种情况,那么我们将需要进入可能会减慢查询的速度,我的Python技能不存在所以我无法帮助你对不起!
如果情况并非如此,那么我可能会考虑在$('#navPersonSearch')
调用typeahead:initialized
和typeahead:opened
时进行一些记录,看看它们是否会带来奇怪的结果。
答案 3 :(得分:0)
您可以使用django haystack,服务器端代码大致如下:
def autocomplete(request):
sqs = SearchQuerySet().filter(content_auto=request.GET.get('q', ''))[:5] # or how many names you need
suggestions = [result.first_name for result in sqs]
# you have to configure typeahead how to process returned data, this is a simple example
data = json.dumps({'q': suggestions})
return HttpResponse(data, content_type='application/json')