dom*_*nho 6 database django caching python-2.7 prometheus
我有一个名为Apache Prometheus监控和模型的Django应用程序Sample.
我想监视Sample.objects.count()指标并将此值缓存为具体的时间间隔,以避免在数据库中进行昂贵的COUNT(*)查询.
从本教程 https://github.com/prometheus/client_python#custom-collectors 我读到我需要编写自定义收集器.
实现这一目标的最佳方法是什么?在django中是否有任何方法可以获得Sample.objects.count()缓存值并在K秒后更新它?我也在我的应用程序中使用Redis.我应该存储这个值吗?我应该制作单独的线程来更新Sample.objects.count()缓存值吗?
首先要注意的是,您并不需要缓存count(*)查询的结果.
虽然不同的RDBMS处理计数操作的方式不同,但对于大型表,它们的速度很慢.但他们有一个共同点是RDBMS提供了SELECT COUNT(*)的替代方法,它实际上是一个缓存结果.好吧.
你没有提到你的RDBMS是什么,所以让我们看看它与Django一起使用的流行版本
如果您的桌子上有主键并且您正在使用MyISAM.SELECT COUNT()在mysql上非常快,并且可以很好地扩展.但是你可能正在使用Innodb.由于各种原因,这是正确的存储引擎.Innodb是事务感知的,无法处理COUNT()以及MyISAM,随着表的增长,查询速度变慢.
具有2M记录的表上的计数查询花费0.2317秒.以下查询花了0.0015秒
SELECT table_rows FROM information_schema.tables
WHERE table_name='for_count';
Run Code Online (Sandbox Code Playgroud)
但它报告的值为1997289而不是200万但足够接近!
所以你不需要自己的缓存系统.
Sqlite COUNT(*)查询并不是很慢,但它也没有扩展.随着表大小的增加,计数查询的速度变慢.使用类似于mysql中使用的表,SELECT COUNT(*) FROM for_count需要0.042秒才能完成.
没有捷径.该sqlite_master表不提供行计数.也没有pragma table_info
您需要自己的系统来缓存SELECT COUNT(*)的结果
尽管postgresql是功能最丰富的开源RDBMS,但它并不擅长处理count(*),它速度慢且不能很好地扩展.换句话说,与糟糕的关系没有什么不同!
postgreql上的count查询花了0.194秒.另一方面,以下查询花了0.003秒.
SELECT reltuples FROM pg_class WHERE relname = 'for_count'
Run Code Online (Sandbox Code Playgroud)
您不需要自己的缓存系统.
SQL服务器上的COUNT查询平均花费0.160秒,但波动相当大.对于此处讨论的所有数据库,第一次计数(*)查询速度相当慢,但后续查询速度更快,因为文件是由操作系统缓存的.
我不是SQL服务器的专家,所以在回答这个问题之前,我不知道如何使用架构信息查找行数.我发现这个Q&A很有帮助.我试过的其中一个产生了0.004秒的结果
SELECT t.name, s.row_count from sys.tables t
JOIN sys.dm_db_partition_stats s
ON t.object_id = s.object_id
AND t.type_desc = 'USER_TABLE'
AND t.name ='for_count'
AND s.index_id = 1
Run Code Online (Sandbox Code Playgroud)
你不需要自己的缓存系统.
可以看出,除了sqlite之外所有考虑的数据库都提供了内置的"缓存查询计数".我们不需要创建自己的数据库.创建客户经理以利用此功能是一件简单的事情.
class CustomManager(models.Manager):
def quick_count(self):
from django.db import connection
with connection.cursor() as cursor:
cursor.execute("""SELECT table_rows FROM information_schema.tables
WHERE table_name='for_count'""")
row = cursor.fetchone()
return row[0]
class Sample(models.Model):
....
objects = CustomManager()
Run Code Online (Sandbox Code Playgroud)
上面的例子是针对postgresql的,但是只需将查询更改为上面列出的一个,就可以将相同的东西用于mysql或sql server.
如何将其插入django prometheus?我把它留作练习.