“匿名块”是 Oracle 的一个术语。但是说到 sql server
Declare
....
Begin
begin trans
. . .
commit
End
如果我通过 ADO.NET 以参数化的形式将此 SQL 发送到服务器,它会被缓存并重用还是每次都重新编译?
“匿名块”是 Oracle 的一个术语。但是说到 sql server
Declare
....
Begin
begin trans
. . .
commit
End
如果我通过 ADO.NET 以参数化的形式将此 SQL 发送到服务器,它会被缓存并重用还是每次都重新编译?
另一个问题来自我发现EXPLAIN
PostgreSQL 中很棒的新选项。这一个侧重于BUFFERS
选项。
这是解释:
EXPLAIN (ANALYZE, BUFFERS) SELECT event_time FROM ui_events_v2 WHERE page ~ 'foo' LIMIT 1;
QUERY PLAN
---------------------------------------------------------------------------------------------------------------------
Limit (cost=0.00..1539.68 rows=1 width=8) (actual time=0.858..0.858 rows=1 loops=1)
Buffers: shared read=10
I/O Timings: read=0.735
-> Seq Scan on ui_events_v2 (cost=0.00..3313394.58 rows=2152 width=8) (actual time=0.857..0.857 rows=1 loops=1)
Filter: (page ~ 'foo'::text)
Rows Removed by Filter: 112
Buffers: shared read=10
I/O Timings: read=0.735
Planning Time: 6.455 ms
Execution Time: 0.877 ms
它非常快 - 而且这个查询在冷启动时非常慢。这是一个 30M 行的表,七行page
包含 substring foo
。与此查询匹配的第一行似乎显示了 604k 页面,这将是中提到的 ~3M 页面的 ~20% pg_class
:
SELECT min(ctid) FROM ui_events_v2 WHERE page ~ 'foo';
min
-------------
(604435,10)
我的假设是,即使该表的每个页面都在 PostgreSQL 或操作系统缓存中,它仍然需要遍历一些线性页面列表以进行顺序扫描。sectionBuffers: shared read=10
和0.877 ms
执行时间向我表明,它以某种方式“从中断的地方开始”并从远离开始的页面开始。我认为它通过页面 ID 移动并在移动时尝试查看每个页面的缓存,但它是否可能从缓存本身开始?如果是这样,它如何发现非缓存页面?
我知道不能保证以任何特定顺序找到行,但我认为在相同的查询策略中,遵循的路径会相对相似。
据我所知,SQL Server 会自动管理缓冲池组件的大小。我想知道是否可以为计划缓存和数据缓存设置预定义的大小?
我们正在使用带有 Galera 插件的 MariaDB 10.2。集群由 4 个节点组成 - 3 个用于繁忙的服务复杂查询,1 个用于备份。
最近我们遇到了 ProxySQL,这听起来对我们来说非常有趣,因为它可以将插入查询拆分到一台服务器并从其他服务器中选择数据。我们希望避免在高活动期间出现死锁和自动增量问题。
但是我们的一位开发人员发现了一个延迟——在使用 ProxySQL 时,他尝试插入一条简单的记录并立即选择该记录。一般来说,每隔一秒或三秒这样的选择请求就会因延迟而失败。如果他添加微小的 0.01 秒延迟 - 他永远不会失败,因为所有 galera 节点都能够在这段时间内同步。
现在的问题是 - 是否可以使用 ProxySQL 缓存插入的数据,因此至少在前 0.01 秒内会从缓存中返回即时“选择”。
或者在这种情况下还有其他方法或建议吗?
谢谢你。:)
我想弄清楚 Postgres 的关系和目录缓存是按连接还是按服务器?我确实发现计划缓存是针对每个连接的。只要服务器正在运行,缓存就会存在,但我找不到任何关于它的文档。
如果您查看https://redis.io/commands#list之类的内容,您会发现 Redis 存储和支持的类型在数据存储的内存中是完全可变的、原子的。
这没有多大意义,因为 Redis 主要作为缓存存在,以加速应用程序,这些应用程序具有与 Redis 分开的数据库,并且仅将 Redis 用作从中读取值的地方。
我在这里错过了什么?当不适合缓存模型时,为什么直接在 Redis 上对值进行可变性?
我试图了解 MySQL 的内部结构。我知道 MySQL 的缓冲池管理有一个旧/新页面列表,如此处所示。而且我确实知道旧的脏页的刷新,比如这里解释的以及如何在这里自定义它。我也知道 MySQL 使用 LRU 算法进行页面驱逐,如下所示。
但是,是否有一个缓冲池守护进程/线程可以驱逐通过 select 语句带到缓冲池的只读页面(不是脏页)?有没有办法自定义它(例如,当我通过 95% 的缓冲池容量时,开始驱逐读取的页面或刷新脏页)。换句话说,LRU 算法中的什么触发器从缓冲池中逐出页面(例如,页面在缓冲池中的时间、缓冲池填充的百分比、需要逐出页面以加载新页面),这些是否可调?
SQL Server 是否会缓存非持久化计算列的结果以便可以重复使用而不会产生重新计算的成本?
附加上下文 我一直建议如果使用计算列,你应该使用 PERSISTED 选项,除非你期望插入/更新频率高于读取频率,或者你需要比读取更好的插入/更新性能数据(即因为计算成本必须在其中一个或另一个上产生,所以决定实际上是你想支付该成本的地方)。
还考虑了计算数据的额外存储,但通常这可以忽略不计且便宜,因此无需过多考虑。
但是,我想检查我的建议是否完全准确,因为 SQL 可能更智能……即一旦 SQL 计算出一个计算列,它就可以将这个值记录在内存中,这样它就不必在后续的计算中重新计算该值查询。SQL 可以在缓存值上有一个时间戳,在基础记录数据上有另一个时间戳,以说明自计算值计算以来该记录是否已更改,以确定缓存值是否仍然有效。
是否有类似的东西/它是否取决于可用资源(例如内存)或其他因素(例如缓存值是否具有超出进程生命周期的 TTL)?我从来没有读过任何暗示这存在的东西,但如果没有在幕后进行一些优化,我会感到惊讶。
在 Dynamics AX 中有一种缓存机制,可以将表配置为加载到内存中并进行缓存。此缓存限制为一定数量的 KB 以防止内存问题。我正在谈论的设置被调用entiretablecache
,并在请求单个记录后立即将整个表加载到内存中。
直到最近,我们依靠一些脚本来验证具有此设置的表的大小,以查看表大小是否超过此限制。
然而现在,压缩开始发挥作用,像sp_spaceused或sys.allocation_units这样的东西似乎报告了压缩数据实际使用的空间。
显然,应用程序服务器正在处理未压缩的数据,因此 SQL Server 中磁盘上的数据大小无关紧要。我需要未压缩数据的实际大小。
我知道sp_estimate_data_compression_savings但顾名思义,这只是一个估计值。
我希望尺寸尽可能正确。
我能想到的唯一方法是一些复杂的动态 SQL 创建与压缩表具有相同结构的未压缩表,将压缩数据插入该影子表中,然后检查该影子表的大小。
不用说,这有点乏味,并且需要一段时间才能在数百 GB 的数据库上运行。
Powershell 可能是一个选项,但我不想遍历所有表以select *
对它们执行 a 以检查脚本中的大小,因为这只会淹没缓存并且可能也需要很长时间。
简而言之,如果可能的话,我需要一种方法来获取每个表的大小,因为它一旦被解压缩并且在呈现给应用程序的等式中会出现碎片。我对不同的方法持开放态度,首选 T-SQL,但我不反对 Powershell 或其他创造性方法。
假设应用程序中的缓冲区是数据的大小。bigint 始终是 bigint 的大小,字符数据类型是每个字符 2 个字节(unicode)。BLOB 数据也采用数据的大小,枚举基本上是一个 int,数字数据是 numeric(38,12),datetime 是 datetime 的大小。此外,没有NULL
值,它们要么存储为空字符串,要么存储1900-01-01
为零。
没有关于如何实现的文档,但假设是基于一些测试以及 PFE 和支持团队使用的脚本(显然也忽略了压缩,因为检查是内置在应用程序中的,应用程序无法分辨如果基础数据被压缩),它还会检查表大小。例如,此链接指出:
避免对大型表使用 EntireTable 缓存(在 AX 2009 中超过 128 KB 或 16 页,在 AX 2012 中超过“整个表缓存大小”应用程序设置 [默认值:32KB 或 4 页])——改为使用记录缓存。