我找到了很多关于什么 的信息STATISTICS:如何维护它们,如何从查询或索引手动或自动创建它们,等等。但是,我一直无法找到有关何时的任何指导或“最佳实践”信息创建它们:在哪些情况下,手动创建的 STATISTICS 对象比索引更受益。我已经看到手动创建的过滤统计有助于对分区表的查询(因为为索引创建的统计覆盖了整个表而不是每个分区——brillaint!),但肯定有其他场景可以从统计对象中受益,同时不需要索引的详细信息,也不值得维护索引或增加阻塞/死锁机会的成本。
@JonathanFite 在评论中提到了索引和统计数据之间的区别:
索引将通过创建排序与表本身不同的查找来帮助 SQL 更快地找到数据。统计信息帮助 SQL 确定满足查询需要多少内存/工作量。
这是很好的信息,主要是因为它帮助我澄清了我的问题:
如何知道这(或在任何其他技术信息什么S和如何S的相关的行为和性质STATISTICS)帮助确定何时选择CREATE STATISTICS在CREATE INDEX创建索引将创建相关的时候,尤其是STATISTICS对象?什么情况下只有统计信息而没有索引会更好地服务?
如果可能的话,有一个场景的工作示例,其中STATISTICS对象比INDEX.
由于我是一名视觉学习者/思考者,我认为将esSTATISTICS和INDEXes之间的差异并排查看可能有助于确定何时STATISTICS是更好的选择。
Thingy PROs CONs
------- ---------- -------------------
INDEX * Can help sorts. * Takes up space.
* Contains data (can * Needs to be maintained (extra I/O).
"cover" a …Run Code Online (Sandbox Code Playgroud) 我正在尝试确定 MySQL 优化器在估计(准备)查询的成本时从何处获取可用于表的索引列表。
我刚刚了解到,我工作的一家客户公司决定关闭其某些 SQL Server 的自动更新统计选项,并且 DBA 在性能问题出现时手动排除故障。
然而,这种对我来说没有意义。为什么要阻止更新统计信息?
在 Postgres 8.4 上执行以下操作时:
select * from pg_stat_all_indexes where relname = 'table_name';
Run Code Online (Sandbox Code Playgroud)
它返回字段 idx_tup_read 和 idx_tup_fetch,有什么区别?
在 MYSQL 状态下,Handler_read_rnd_next 值非常高。
我知道,当执行没有正确索引的查询时,此值将增加。
但是,即使我们执行像“Handler_read_rnd_next”这样的显示状态,这个值也会增加 2。
基于这个状态标志,我们正在监控一些统计数据。
所以每一次,这个统计数据都显示出关键性。
我们能否从“Handler_read_rnd_next”计数中排除这些“显示”执行计数。
再举一个例子,
有一个 10 行的表,表在列 'data' 上建立索引,如果我们执行以下查询:
select data from test where data = 'vwx' -> returns one row
Run Code Online (Sandbox Code Playgroud)
如果我们检查 'Handler_read_rnd_next' 的值,它会增加 7。
以下是上述查询的解释命令的结果:
explain select data from test where data = 'vwx';
id, select_type, table, type, possible_keys, key, key_len, ref, rows, Extra
1, 'SIMPLE', 'test', 'ref', 'data', 'data', '35', 'const', 1, 'Using where; Using index'
Run Code Online (Sandbox Code Playgroud)
有没有办法限制这个值,或者我能知道为什么这个值增加得非常快。
当我这样做时,dbcc show_statistics ('Reports_Documents', PK_Reports_Documents)我会得到报告 ID 18698 的以下结果:

对于此查询:
SELECT *
FROM Reports_Documents
WHERE ReportID = 18698 option (recompile)
Run Code Online (Sandbox Code Playgroud)
我得到一个查询计划,PK_Reports_Documents按预期进行聚集索引搜索。
但让我感到困惑的是估计行数的错误值:

根据这个:
当示例查询 WHERE 子句值等于直方图 RANGE_HI_KEY 值时,SQL Server 将使用直方图中的 EQ_ROWS 列来确定等于的行数
这也是我所期望的方式,但在现实生活中似乎并非如此。我还尝试RANGE_HI_KEY了由提供的直方图中存在的一些其他值,show_statistics并经历了相同的情况。在我的情况下,这个问题似乎导致某些查询使用非常不理想的执行计划,导致执行时间为几分钟,而我可以通过查询提示在 1 秒内运行它。
总而言之:有人可以解释一下为什么EQ_ROWS直方图没有用于估计的行数,不正确的估计来自哪里?
更多(可能有用)信息:
PK_Reports_Documents是一个组合PK,由ReportID INT和DocumentID CHAR(8)该查询似乎总共加载了 5 个不同的统计对象,所有这些对象都包含ReportID表中的 + 一些其他列。它们都已新鲜更新。RANGE_HI_KEY下表中是直方图中的最高上限列值。
+-------------------------------------------------------------------------+----------+--------------+--------------+---------------------+--------------+------------+----------+---------------------+----------------+
| name | stats_id | auto_created | user_created | Leading column Type …Run Code Online (Sandbox Code Playgroud) sp_updatestats在生产环境中的 SQL Server上运行是否安全?
或者更确切地说,更新 sql server 上的所有统计信息有什么影响?它可以在运行时“阻塞”sql server 并导致用户超时或其他问题吗?
出于查询优化和测试的目的,您可以通过运行UPDATE STATISTICS. 但是你如何重新计算/重置统计数据到表格的实际内容?
--- Create a table..
CREATE TABLE dbo.StatTest (
i int NOT NULL,
CONSTRAINT PK_StatTest PRIMARY KEY CLUSTERED (i)
);
GO
--- .. and give it a thousand-or-so rows:
DECLARE @i int=1;
INSERT INTO dbo.StatTest (i) VALUES (@i);
WHILE (@i<1000) BEGIN;
INSERT INTO dbo.StatTest (i) SELECT @i+i FROM dbo.StatTest;
SET @i=@i*2;
END;
Run Code Online (Sandbox Code Playgroud)
一个虚拟查询:
SELECT i%100, COUNT(*) FROM dbo.StatTest GROUP BY i%100;
Run Code Online (Sandbox Code Playgroud)
... 将返回以下查询计划(索引扫描中的行估计为 1024 行)。
运行UPDATE STATISTICS命令..
UPDATE STATISTICS dbo.StatTest WITH ROWCOUNT=10000000;
Run Code Online (Sandbox Code Playgroud)
...计划看起来像这样,现在估计有 1000 …
作为更广泛的收购项目的一部分,我刚刚继承了大约 20 个 SQL Server 实例。我正在评估性能,我不喜欢维护计划的实施方式。
我每天都在看到全面的索引重建(我可以处理这个)以及每天手动更新统计数据。
大约一半的数据库已设置为 Auto Update Statistics = False,原因尚不清楚,除了我被告知是为了减少“性能问题”...
我一直认为并致力于将其设置为 True 的最佳实践,并认为如果此设置为 True,则不需要手动更新。我错了吗?
任何人都可以解释将此设置为 False 的好处是什么,而是每天进行手动更新?
我应该提到一些数据库是高度事务性的(每天数百万次插入、删除、更新),其他数据库在事务率方面很低,有些几乎是只读的。虽然没有押韵或理由将自动更新设置设置为 False。好像是彩票。
我们有一个大型(10,000 多行)程序,通常在 0.5-6.0 秒内运行,具体取决于它必须处理的数据量。在过去一个月左右的时间里,在我们使用 FULLSCAN 进行统计更新后,它开始需要 30 多秒的时间。当它变慢时,sp_recompile 会“修复”该问题,直到夜间统计作业再次运行。
通过比较慢速和快速执行计划,我将范围缩小到特定的表/索引。当它运行缓慢时,它估计将从特定索引返回约 300 行,当它运行得快时,它估计将返回 1 行。当它运行缓慢时,它在对索引进行查找后使用表假脱机,当它运行快时它不执行表假脱机。
使用 DBSS SHOW_STATISTICS,我在 excel 中绘制了索引直方图。我通常希望图表更像“起伏的山丘”,但相反,它看起来像一座山,最高点比图表上的大多数其他值高 2 到 3 倍。

如果我更新它的统计数据,没有 FULLSCAN,它看起来更正常。如果我然后再次使用 FULLSCAN 运行它,它看起来就像我上面描述的那样。
这感觉像是一个参数嗅探问题,特别与上面(看似)奇怪的索引分布有关。
proc 接受一个表值参数,参数嗅探可以发生在表值参数上吗?
编辑:proc 还需要 12 个其他参数,其中一些是可选的,其中两个是开始日期和结束日期。
直方图是奇怪的,还是我叫错了树?
我当然愿意尝试调整查询和/或尝试调整我的索引。如果这是一个很好的解决方案,那么我的问题更多是关于偏斜直方图。
我应该提到这是一个 PK IDENTITY 聚集索引。我们有两个相互通信的系统,一个是遗留系统,一个是新的本土系统。两个系统都存储相似的数据。为了使它们保持同步,当向旧系统添加事物时,新系统中此表上的 PK 会增加,即使数据没有过来(已完成 RESEED)。因此,此列中的编号可能存在一些空白。记录很少被删除,如果有的话。
任何想法将不胜感激。我很高兴收集/包含更多信息。
sql-server sql-server-2008-r2 parameter index-statistics index-tuning
index-statistics ×10
sql-server ×7
statistics ×4
mysql ×2
index-tuning ×1
parameter ×1
performance ×1
postgresql ×1