如何查看Sqlalchemy编译缓存中的条目数量?

How can I view the amount of entries in Sqlalchemy's compiled cache?

Sqlalchemy 的 compiled cache of SQL 语句是“类似字典的对象”,其大小是可配置的。但是,我如何才能看到已经 运行 一段时间的应用实际使用了多少条目?

文档说

To estimate the optimal size of the cache, assuming enough memory is present on the target host, the size of the cache should be based on the number of unique SQL strings that may be rendered for the target engine in use. The most expedient way to see this is to use SQL echoing

虽然回显对于其他信息很有用,但我没有看到任何明确的方法来使用它来确定缓存中实际有多少项目。它列出了语句以及它们是缓存命中还是未命中、缓存键生成时间等,但是从中找出缓存中有多少条目似乎并不简单。

我想做类似 len(compiled_cache) 的事情,目的是大致了解一个应用程序实际使用了多少唯一(可缓存)查询。

默认缓存继承自collections.abc.MutableMapping,所以原则上可以调用len()或者像普通字典一样显示:

>>> engine = sa.create_engine('mysql:///test', echo=True, future=True)
>>> engine._compiled_cache                                            
{}
>>> conn = engine.connect()                            
2022-04-10 08:04:37,511 INFO sqlalchemy.engine.Engine SELECT DATABASE()
2022-04-10 08:04:37,511 INFO sqlalchemy.engine.Engine [raw sql] ()
2022-04-10 08:04:37,512 INFO sqlalchemy.engine.Engine SELECT @@sql_mode
2022-04-10 08:04:37,512 INFO sqlalchemy.engine.Engine [raw sql] ()
2022-04-10 08:04:37,513 INFO sqlalchemy.engine.Engine SELECT @@lower_case_table_names
2022-04-10 08:04:37,513 INFO sqlalchemy.engine.Engine [raw sql] ()
>>> res = conn.execute(sa.text('select * from username'))             
2022-04-10 08:04:48,566 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2022-04-10 08:04:48,566 INFO sqlalchemy.engine.Engine select * from username
2022-04-10 08:04:48,566 INFO sqlalchemy.engine.Engine [generated in 0.00054s] ()
>>> len(engine._compiled_cache)
1
>>> # Cache hit doesn't affect size
>>> res = conn.execute(sa.text('select * from username'))
2022-04-10 08:05:20,693 INFO sqlalchemy.engine.Engine select * from username
2022-04-10 08:05:20,693 INFO sqlalchemy.engine.Engine [cached since 32.13s ago] ()
>>> len(engine._compiled_cache)
1
>>> res = conn.execute(sa.text('select id from username'))
2022-04-10 08:05:47,376 INFO sqlalchemy.engine.Engine select id from username
2022-04-10 08:05:47,376 INFO sqlalchemy.engine.Engine [generated in 0.00041s] ()
>>> len(engine._compiled_cache)
2
>>> # We can display the cache if we want to
>>> engine._compiled_cache
{
    (<sqlalchemy.dialects.mysql.mysqldb.MySQLDialect_mysqldb object at 0x7f0042c90c10>, ('0', <class 'sqlalchemy.sql.elements.TextClause'>, 'text', 'select * from username'), (), False, False): [
        (
            <sqlalchemy.dialects.mysql.mysqldb.MySQLDialect_mysqldb object at 0x7f0042c90c10>,
            ('0', <class 'sqlalchemy.sql.elements.TextClause'>, 'text', 'select * from username'),
            (),
            False,
            False
        ),
        <sqlalchemy.dialects.mysql.mysqldb.MySQLCompiler_mysqldb object at 0x7f0042c93a30>,
        2
    ],
    (<sqlalchemy.dialects.mysql.mysqldb.MySQLDialect_mysqldb object at 0x7f0042c90c10>, ('0', <class 'sqlalchemy.sql.elements.TextClause'>, 'text', 'select id from username'), (), False, False): [
        (
            <sqlalchemy.dialects.mysql.mysqldb.MySQLDialect_mysqldb object at 0x7f0042c90c10>,
            ('0', <class 'sqlalchemy.sql.elements.TextClause'>, 'text', 'select id from username'),
            (),
            False,
            False
        ),
        <sqlalchemy.dialects.mysql.mysqldb.MySQLCompiler_mysqldb object at 0x7f0042e849d0>,
        3
    ]
}
>>> 

实际上,len 可能仅在多个并发连接正在生成新条目时才具有指示性,一旦缓存已满就会趋于平稳。