我有一个由某个应用程序创建的数据库。整个数据库超过50 GB,备份出现了一些问题,我的任务是让这个数据库尽可能小。
特别是一个表非常大(22 gb),其中16.5 gb是由索引获取的,其余5.5 gb是数据。它包含的行数不超过12 000 000行。
你能告诉我是否可以缩小索引?我已经尝试过重建,重新组织,重新创建聚簇索引,dbcc清晰。我也知道nvarchar类型的大小比varchar大两倍,所以我将列类型更改为varchar,但是由于我节省了大约2 GB(数据上1 gb和索引上1 gb)。
这是这个表的一个sql(fld0和fld1总是NULL):
CREATE TABLE [dbo].[DOC8](
[ASSOCIATION] [nvarchar](64) NULL DEFAULT (NULL),
[DOCID] [char](32) NOT NULL,
[FLD0] [nvarchar](255) NULL DEFAULT (NULL),
[FLD1] [nvarchar](2048) NULL DEFAULT (NULL),
[FLD10] [nvarchar](255) NULL DEFAULT (NULL),
[FLD2] [nvarchar](32) NULL DEFAULT (NULL),
[FLD3] [nvarchar](255) NULL DEFAULT (NULL),
[FLD4] [nvarchar](255) NULL DEFAULT (NULL),
[FLD5] [datetime] NULL DEFAULT (NULL),
[FLD6] [nvarchar](255) NULL DEFAULT (NULL),
[FLD7] [nvarchar](255) NULL DEFAULT (NULL),
[FLD8] [nvarchar](255) NULL DEFAULT (NULL),
[FLD9] [datetime] NULL DEFAULT (NULL),
[PARENTID] [char](32) NULL DEFAULT (NULL),
[POOLID] [char](32) NULL DEFAULT (NULL),
[PROPERTIES] [ntext] NULL DEFAULT (NULL),
[FLD11] [nvarchar](255) NULL DEFAULT (NULL),
[FLD12] [nvarchar](255) NULL DEFAULT (NULL),
PRIMARY KEY CLUSTERED
(
[DOCID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]
GO
SET ANSI_PADDING OFF
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_0] ON [dbo].[DOC8]
(
[ASSOCIATION] ASC,
[PARENTID] ASC,
[POOLID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_1] ON [dbo].[DOC8]
(
[POOLID] ASC,
[FLD0] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_10] ON [dbo].[DOC8]
(
[POOLID] ASC,
[FLD11] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_11] ON [dbo].[DOC8]
(
[POOLID] ASC,
[FLD12] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_2] ON [dbo].[DOC8]
(
[POOLID] ASC,
[FLD2] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_3] ON [dbo].[DOC8]
(
[POOLID] ASC,
[FLD3] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_4] ON [dbo].[DOC8]
(
[POOLID] ASC,
[FLD4] ASC,
[FLD5] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_5] ON [dbo].[DOC8]
(
[POOLID] ASC,
[FLD6] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_6] ON [dbo].[DOC8]
(
[POOLID] ASC,
[FLD7] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_7] ON [dbo].[DOC8]
(
[POOLID] ASC,
[FLD8] ASC,
[FLD9] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_8] ON [dbo].[DOC8]
(
[POOLID] ASC,
[FLD10] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
CREATE NONCLUSTERED INDEX [DOC8_IDX_9] ON [dbo].[DOC8]
(
[PARENTID] ASC,
[POOLID] ASC,
[DOCID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
GO
答案 0 :(得分:7)
查看您的表定义
主键:
列:
索引:
您的主要问题是聚集索引选择不当。如果你无法解决这个问题,那么其他一切都是毫无意义的:除非你删除数据......
当您更改为varchar时,您从22GB中节省了2GB。这是9%,这是相当合理的,没有其他优化。它还表明你不需要nvarchar ...
如果更改为int代理键,则每个非聚集索引每行可节省28个字节。 这是最低3.7 GB(12 x 12,000,000 x 28),但由于每页有更多行,因此会更多。它对客户端代码透明。
然后开始检查索引使用情况......
但是,您应该查看容量规划和数据增长计划。我在这里建议的更改将减少增长率以及当前大小,但如果您需要另外5000万行,那么您需要为此计划。例如,您可以压缩备份吗?
答案 1 :(得分:6)
查找未使用的索引并将其删除。这也将减少驱动器为dui(删除,更新和插入)所做的写入量。 请参阅Brent Ozar的博客,了解如何执行此操作: http://www.toadworld.com/platforms/sql-server/w/wiki/10062.find-indexes-not-in-use
基本上,如果你的读/写很低(<0.1),那么索引对你的伤害超过了它的帮助,并且可能还需要去。在删除索引之前,您需要仔细考虑。
您也可以从过滤后的索引中受益。 http://sqlfool.com/2009/04/filtered-indexes-what-you-need-to-know/
答案 2 :(得分:4)
您可以检查是否实际使用了所有索引并删除了您不需要的索引,但通常您正以错误的方式解决问题 - 即使您设法创建数据库今天变小,它会继续增长,并且在几个月内你将再次遇到同样的问题。
除非数据库包含许多您可以删除的不必要的数据和/或索引,否则您必须找到管理此类大小的数据库的方法。
在开始删除列和索引之前,更改列的数据类型,您需要绝对确定这将如何影响应用程序操作和性能。但是,这是第三方软件,其开发人员将在接下来的几天内不回答您的问题(他们直到今年年底才开始工作),所以绝对没有办法预测这种盲目数据库结构变化的所有负面影响。系统不会立即失败,但是您的更改与未来的软件更新(由不了解您所做的修改的人准备)可能会产生灾难性的后果。
答案 3 :(得分:1)
明确地检查索引,你真的需要模式的所有索引吗? [POOLID],[FLD]?如果他们的存在不合理,那么他们就不应该存在。
我假设DOCID等是没有连字符的GUIDS。 如果你可以重新开始,我会选择使用内置的guid类型而不是char32,这会减少你所拥有的凹痕的大小,但这不是一个简单的改变,因为微软是愚蠢的,所以你必须把连字符放在他们的guid类型然后应用程序必须在结构中有额外的空间或翻译连字符。
答案 4 :(得分:0)
在解决这个问题后,我来到了最后阶段: - 数据从5 451 477 MB减少到4 088 609 MB - 索引从15 361 391 MB减少到6 003 094 MB
以下是我所做的步骤(可能对某些人有用):
感谢您帮助我解决此问题:)