Python postgreSQL非常慢

时间:2019-04-03 14:39:50

标签: python sql postgresql heroku flask-sqlalchemy

我正在进行x的for循环,该循环是通过1个表列出30-50个URL的列表,以查看是否有任何URL匹配---(花费了超过 5秒< / strong>)

关于此系统

  • 这是来自 Heroku.com 的免费数据库,我正在将其用作测试
  • 如代码中所述,我正在使用“ postgreSQL
  • 我正在使用 flask_sqlalchemy
  • 我正在运行本地托管的主机,因此前端和后端是我的笔记本电脑,它是 i5 1.9ghz和8g rams。
  • 时间戳差异大约为 5秒 ,仅通过本地1位用户在线查看这些 50个条目 < / li>

python代码。

from flask_sqlalchemy import SQLAlchemy 
app.config['SQLALCHEMY_DATABASE_URI'] = "postgres://***" 
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = "True" 
db = SQLAlchemy(app,session_options={"autoflush": False}) 

class test1(db.Model): 
    id = db.Column(db.Integer, primary_key = True) 
    url = db.Column(db.String(255)) 
    code = db.Column(db.String(255)) 


    def __init__ (self,url,code): 
        self.url = url 
        self.code = code 

x = [url1,url2,url3,url4,....url50] 

t2 = datetime.time(datetime.now()) 
print("before : ",t2) 

for key in x: 

    y = test1.query.filter(test1.url == key).all() 
    if y: 
        print('----i got it') 
    else: 
        print('no') 

t3 = datetime.time(datetime.now()) 
print("after forloop : ",t3) 

我问过聊天室中的许多人,其中许多人有不同的怀疑,但没人能确定为什么在一个简单的过程中会有如此大的延迟。

2 个答案:

答案 0 :(得分:1)

您要为每个测试创建单独的查询,这需要将新的SQL语句发送到数据库服务器。

对于位于同一服务器上的本地数据库,这并不是什么大问题。但是在Heroku上,数据库 not 不在同一服务器上。该数据库位于云中的其他位置,并且这两个位置彼此接近还是相距甚远,这取决于您的特定配置。

连接到来自非洲的任何 Heroku托管的Postgres数据库将因延迟而变慢。该延迟与您进行的查询数量有关。

您可以使用一个简单的命令测试延迟时间:

time psql postgresql://*** -c select 1;

real user 组件之间的区别大约是一个非常简单的查询到达数据库服务器并返回响应所花费的往返时间。给你。

如果在部署在Heroku 上的查询遇到很大的延迟,则您的数据库实例和Web Dyno可能位于两个不同的区域。至少将一个或另一个迁移到相同地区。如果要从自己的计算机连接到数据库,则还会看到较大的延迟。

在命令行上,运行heroku info命令以检查您的应用程序所在的区域(查找Region行)。或检查您的应用程序Heroku仪表板上的设置标签。有关更多信息,请参见Heroku Regions documentation,如果想将其移至其他区域,请继续阅读migrating apps

我相信,如果要将数据库移至与应用相同的区域,则必须重新创建它。创建并下载完整备份,删除数据库附加组件,重新创建它,并在与应用程序相同的区域中创建。然后从备份中还原数据库。

即使您的应用程序dyno和数据库位于同一区域,您仍然会看到比本地计算机上安装Flask和Postgres更大的延迟。您将看到多少延迟还取决于特定的Heroku Postgres plan you pick。 Hobby层(免费)仅允许20个连接,并且没有没有内存中缓存,因此您将需要更频繁地重用连接,并且您不能指望具有缓存表的服务器这些信息对于一系列相关查询很有用。

答案 1 :(得分:0)

您可以使用in_查询一次并在内存中进行搜索,而不是在循环中进行查询。

test1_objs = test1.query.filter(test1.url.in_(x)).all()
test1_urls = set()
for test1_obj in test1_objs:
    test1_urls.add(test1_obj.url)
for key in x: 
    if key in test1_urls: 
        print('----i got it') 
    else: 
        print('no') 

这将减少时间,但我认为这是由于网络延迟而发生的。如果您在云上使用服务器,然后重试,则延迟会更少。