SQL 服务器数据库的 'optimizing' 索引的奇怪结果,原因是什么?
Weird result of 'optimizing' indices of a SQL Server database, what's the reason?
我偶然发现了一个日志数据库,它旨在保留过去 60 天的数据并提供索引,从而实现快速数据分析。
数据库由 26GB 数据 space 和 10GB 索引存储组成,在分析了我认为的索引后,大约 50% 从未使用过或效率低下,因此我设置执行以下更改:
旧
IX MODE SIZE
------------------------------------------------------------------------
PK_PerformanceData CLUSTERED 26,09 GB
IX_PerformanceData_Controller NON_CLUSTERED 2,07 GB
IX_PerformanceData_AppName NON_CLUSTERED 1,89 GB
IX_PerformanceData_ControllerMethod NON_CLUSTERED 1,73 GB
IX_PerformanceData_StartTime NON_CLUSTERED 1,35 GB
IX_PerformanceData_AppHost NON_CLUSTERED 1,30 GB
IX_PerformanceData_LogTime NON_CLUSTERED 0,79 GB
IX_PerformanceData_StatusCode NON_CLUSTERED 0,57 GB
IX_PerformanceData_ProcessException NON_CLUSTERED 0,54 GB
新
IX MODE SIZE
---------------------------------------------------------------------
CIX_PerformanceData_AppName_Controller CLUSTERED 26,99 GB
IX_PerformanceData_LogTime NON-CLUSTERED 3,62 GB
IX_PerformanceData_ProvId NON-CLUSTERED 3,61 GB
PK_PerformanceData NON-CLUSTERED 3,57 GB
IX_PerformanceData_ProcessException NON-CLUSTERED 3,34 GB
列:
VARCHAR(n) = Controller, AppName, ControllerMethod, AppHost
DATETIME = StartTime, LogTime
SMALLINT = StatusCode
BIGINT = Id, ProvId
BIT = ProcessException
我将字符串类型的索引更改为单个 CLUSTERED 索引(可能有大约 20 种变化),因为我认为这会产生一个漂亮而花花公子的小型 B-TREE 索引。此外,我删除了一些对期刊没有任何用处的索引。
之前索引存储已经是数据量的40%左右,我怀疑它会下降到10%以下。不幸的是,它们变得异常大,看起来每个索引都指向聚集的字符串文字,因此跳到了大约 52% 的数据 space.
即使是聚簇索引也能更快地工作,现在 space 消耗非常垃圾。任何人都可以解释这个观察结果吗?有什么最佳实践可以解决我的问题吗?
当你有一个聚簇索引时,这将成为所有引用所述 table 的索引的叶节点处的指针。这有助于提高性能,因为如果您检索的数据存储在聚簇索引中,则无需实际转到 table 即可获取它。
最佳做法取决于您的需要。索引以磁盘 space 为代价提高读取性能。当您开始构建包含数据的索引时,例如使用 include 的覆盖索引,存储量会随着读取性能的提高而急剧增加。我相信索引总是写得很慢,不过我可能是错的。
我认为最佳做法是找到适合您的要求和预算的平衡。
我偶然发现了一个日志数据库,它旨在保留过去 60 天的数据并提供索引,从而实现快速数据分析。
数据库由 26GB 数据 space 和 10GB 索引存储组成,在分析了我认为的索引后,大约 50% 从未使用过或效率低下,因此我设置执行以下更改:
旧
IX MODE SIZE
------------------------------------------------------------------------
PK_PerformanceData CLUSTERED 26,09 GB
IX_PerformanceData_Controller NON_CLUSTERED 2,07 GB
IX_PerformanceData_AppName NON_CLUSTERED 1,89 GB
IX_PerformanceData_ControllerMethod NON_CLUSTERED 1,73 GB
IX_PerformanceData_StartTime NON_CLUSTERED 1,35 GB
IX_PerformanceData_AppHost NON_CLUSTERED 1,30 GB
IX_PerformanceData_LogTime NON_CLUSTERED 0,79 GB
IX_PerformanceData_StatusCode NON_CLUSTERED 0,57 GB
IX_PerformanceData_ProcessException NON_CLUSTERED 0,54 GB
新
IX MODE SIZE
---------------------------------------------------------------------
CIX_PerformanceData_AppName_Controller CLUSTERED 26,99 GB
IX_PerformanceData_LogTime NON-CLUSTERED 3,62 GB
IX_PerformanceData_ProvId NON-CLUSTERED 3,61 GB
PK_PerformanceData NON-CLUSTERED 3,57 GB
IX_PerformanceData_ProcessException NON-CLUSTERED 3,34 GB
列:
VARCHAR(n) = Controller, AppName, ControllerMethod, AppHost
DATETIME = StartTime, LogTime
SMALLINT = StatusCode
BIGINT = Id, ProvId
BIT = ProcessException
我将字符串类型的索引更改为单个 CLUSTERED 索引(可能有大约 20 种变化),因为我认为这会产生一个漂亮而花花公子的小型 B-TREE 索引。此外,我删除了一些对期刊没有任何用处的索引。
之前索引存储已经是数据量的40%左右,我怀疑它会下降到10%以下。不幸的是,它们变得异常大,看起来每个索引都指向聚集的字符串文字,因此跳到了大约 52% 的数据 space.
即使是聚簇索引也能更快地工作,现在 space 消耗非常垃圾。任何人都可以解释这个观察结果吗?有什么最佳实践可以解决我的问题吗?
当你有一个聚簇索引时,这将成为所有引用所述 table 的索引的叶节点处的指针。这有助于提高性能,因为如果您检索的数据存储在聚簇索引中,则无需实际转到 table 即可获取它。
最佳做法取决于您的需要。索引以磁盘 space 为代价提高读取性能。当您开始构建包含数据的索引时,例如使用 include 的覆盖索引,存储量会随着读取性能的提高而急剧增加。我相信索引总是写得很慢,不过我可能是错的。
我认为最佳做法是找到适合您的要求和预算的平衡。