目前,我们有许多表在主键上使用 newid() 。这导致了大量的碎片。所以我想更改该列以使用 newsequentialid() 代替。
我认为现有数据仍将保持相当分散,但新数据的分散程度将减少。这意味着我也许应该等待一段时间,然后再将 PK 索引从非聚集更改为聚集。
我的问题是,有人有这样做的经验吗?有什么是我忽略的、应该注意的吗?
我们有一个数据库,其中所有PK都是GUID,大多数PK也是表的聚簇索引.我们知道这很糟糕(由于GUID的随机性).因此,似乎这里基本上有两个选项(完全没有将GUID作为PK扔掉,这是我们做不到的(至少目前不是这样)).
是否有可能在这种情况下提供任何一般性建议?
该应用程序有500多个表,最大的一个目前约150万行,几个表约50万行,其余表显着较低(大多数低于10K).
此外,该应用程序已安装在多个客户站点,因此我们必须考虑现有客户的任何可能的负面影响.
谢谢!
我正在尝试优化具有如下代码的过程:
CREATE TABLE #t1 (c1 int, c2 varchar(20), c3(varchar(50)...)
CREATE CLUSTERED INDEX ix_t1 ON #t1(c3) ON [PRIMARY]
Run Code Online (Sandbox Code Playgroud)
我想通过将 CLUSTERED 索引移动到表声明中来改进它(更适合缓存),但是 c3 不是唯一的,所以这不起作用:
CREATE TABLE #t1 (c1 int, c2 varchar(20), c3 varchar(50)..., UNIQUE CLUSTERED (c3))
Run Code Online (Sandbox Code Playgroud)
有没有办法声明一个在临时表声明中不是唯一的集群?
正如之前已多次讨论并且是已知事实 - 在sql server中的uniqueidentifier主键列上具有聚簇索引将影响性能.
我想要做的是通过发布插入和测量某些指标来观察这个问题.我有2个表独特标识PK; 一个以'newid()'作为默认值,另一个以'newsequentialid()'作为默认值.我计划在每个行中插入大约一百万行并观察INSERT性能.
我应该特别询问什么?如何最好地观察在随机GUID上使用顺序GUID的性能增益?是否有某些系统视图,存储过程提供有关索引页面拆分和/或其他相关信息的统计信息?
我想解决的问题是:
1 - 在我们的数据库中,我们拥有所有表(也包含数百万条记录的表),其中PK id列声明为VARCHAR(36).它上面还有一个聚簇索引当然,当我在线阅读时,它对于性能来说是一件糟糕的事情,也因为db有很多读取,插入,更新和删除.
2 - 我们将Java Web应用程序的Hibernate用作此数据库的ORM
在线阅读后,我开始使用默认选项newsequentialid()将这些列的数据类型更改为UNIQUEIDENTIFIER,因为此选项可以缓解索引的碎片问题.
我注意到碎片问题仍然存在,重建后表格变得非常碎片化(我们每晚都进行完整的索引重建).
然后我看到id列的所有Hibernate映射都包含:
<id name="id" column="id" type="string">
<generator class="guid"/>
</id>
Run Code Online (Sandbox Code Playgroud)
当在我们的系统中发生插入时,日志显示插入是在调用之后完成的select newid(),因此由于这会返回一个随机guid,插入将被放置在索引中的随机点,从而导致碎片(这完全打败了列数据类型更改)我也做了).
所以在另一次在线搜索之后,我试图在Hibernate中实现一个guid生成器,实现接口IdentifierGenerator并使用基于时间的生成器和JUG(http://wiki.fasterxml.com/JugHome).
生成(我认为顺序)id的代码是这样的:
String uuid = null;
EthernetAddress nic = EthernetAddress.fromInterface();
TimeBasedGenerator uuidGenerator = Generators.timeBasedGenerator(nic);
uuid = uuidGenerator.generate().toString();
Run Code Online (Sandbox Code Playgroud)
我相应地改变了映射到这个:
<id name="id" column="id" type="string">
<generator class="my_package.hibernate.CustomSequentialGuidGenerator">
</generator>
</id>
Run Code Online (Sandbox Code Playgroud)
然后我尝试生成一些测试uuids来测试它们的顺序性(以uniqueidentifier方式顺序,所以二进制),这是一个短列表(每个元素在连续之前生成):
314a9a1b-6295-11e5-8d2c-2c27d7e1614f
3d867801-6295-11e5-ae09-2c27d7e1614f
4434ac7d-6295-11e5-9ed1-2c27d7e1614f
491462c4-6295-11e5-af81-2c27d7e1614f
5389ff4c-6295-11e5-84cf-2c27d7e1614f
57098959-6295-11e5-b203-2c27d7e1614f
5b62d144-6295-11e5-9883-2c27d7e1614f
Run Code Online (Sandbox Code Playgroud)
这看起来像按字母顺序排列,但不是二进制顺序.
上面的测试是在测试应用中执行了七次,它不是一个循环.
我试图在声明为唯一标识符的列中插入这些值,并在此列上发出select之后,这是sql server输出的列表:
5389FF4C-6295-11E5-84CF-2C27D7E1614F
314A9A1B-6295-11E5-8D2C-2C27D7E1614F
5B62D144-6295-11E5-9883-2C27D7E1614F
4434AC7D-6295-11E5-9ED1-2C27D7E1614F
3D867801-6295-11E5-AE09-2C27D7E1614F
491462C4-6295-11E5-AF81-2C27D7E1614F
57098959-6295-11E5-B203-2C27D7E1614F
Run Code Online (Sandbox Code Playgroud)
所以我真的不明白我应该做什么,如果我可以使用JUG作为顺序guid生成器来避免我的碎片问题.
这是另一个JUG测试,我尝试了3次运行,每次生成10个带有循环的guid: …
目前我正在阅读B+ Tree基础知识,并对聚集和非聚集索引的空间分配感到困惑。
当我们在 上创建聚集索引时B+ tree,索引将存储在主内存中,并且叶子包含指向实际块的数据指针。块存储在磁盘中,块中包含记录。
现在假设我们有一个表(idname 、 name 、 class ),并且我在和上创建了两个非聚集索引class。我的疑问是非聚集索引将存储在哪里?以及如何搜索query类似内容
select id, name, class from table where id = 3, name='Leo' and class='10'
Run Code Online (Sandbox Code Playgroud)
我的假设:
name现在使用和上的非聚集索引class,我们将找到剩余的字段你认为我的假设正确吗?您能否详细说明一下存储聚集索引的情况?两个索引(聚集索引和非聚集索引是否形成n叉树?)。我无法同时可视化聚集索引和非聚集索引。
当我使用下面的查询为 MS SQL Server 中的列创建索引时
create index IX_indexname on tablename(columnname);
Run Code Online (Sandbox Code Playgroud)
如果不提及它是聚集索引还是非聚集索引,那么将创建什么索引?默认索引是哪个?
我有一个Orders带有CLUSTERED IDENTITY PRIMARY KEY(OrderId)的表(),并且正在通过添加日期列()对数据进行过滤和排序AddDate。有没有一种方法可以告诉查询优化器,其AddDate排序方式与OrderIdis 相同(因此数据AddDate已经被排序)?
SQL Server确实不需要先扫描整个表然后对其进行排序。所有操作所需的是扫描表直到找到结束日期,然后在开始日期之前过滤掉数据并按原样返回(不进行排序)。
例:
SELECT
*
FROM Orders
WHERE AddDate BETWEEN @FromDate AND @ToDate
ORDER BY AddDate
Run Code Online (Sandbox Code Playgroud) 我在SQL Server中有一个表,我希望将插入添加到表的末尾(而不是将它们插入中间的聚类键).这意味着我希望按一些列聚集的表不断增加.
这可以通过在datetime列上进行聚类来实现:
CREATE TABLE Things (
...
CreatedDate datetime DEFAULT getdate(),
[timestamp] timestamp,
CONSTRAINT [IX_Things] UNIQUE CLUSTERED (CreatedDate)
)
Run Code Online (Sandbox Code Playgroud)
但我不能保证两个Things人不会有同一时间.因此,日期时间列无法真正实现我的要求.
我可以添加一个虚拟标识 int列,并在其上添加集群:
CREATE TABLE Things (
...
RowID int IDENTITY(1,1),
[timestamp] timestamp,
CONSTRAINT [IX_Things] UNIQUE CLUSTERED (RowID)
)
Run Code Online (Sandbox Code Playgroud)
但你会发现我的桌子已经成了一个timestamp专栏; 保证单调增加的列.这正是我想要的候选群集密钥的特征.
所以我将表聚集在rowversion(又名timestamp)列上:
CREATE TABLE Things (
...
[timestamp] timestamp,
CONSTRAINT [IX_Things] UNIQUE CLUSTERED (timestamp)
)
Run Code Online (Sandbox Code Playgroud)
我没有添加虚拟标识 int列(RowID)来确保订单,而是使用我已有的.
我正在寻找的是为什么这是一个坏主意的想法; 以及其他更好的想法.
注意:社区维基,因为答案是主观的.
是否可以在sql server 2005中将聚簇索引转换为非聚簇索引或非聚簇索引转换为聚簇索引.
请将此查询转换为聚集索引:
create index index1 on mytable(firstcolumn)
Run Code Online (Sandbox Code Playgroud)
请将此查询转换为非聚集索引:
create clustered index clusindex1 on mytable(cluscolumn)
Run Code Online (Sandbox Code Playgroud) clustered-index ×10
sql-server ×8
sql ×5
guid ×3
indexing ×3
b-tree ×1
hibernate ×1
java ×1
mysql ×1
newid ×1
performance ×1
rowversion ×1
sql-order-by ×1
t-sql ×1
temp-tables ×1
timestamp ×1