将垂直分区应用于新创建的模型是一个好习惯吗?

Rin*_*Dev 5 database-design db2 partitioning

假设您正在为一个新的面向对象的 Web 应用程序建模 ER 模型。

有一个有 20 列的表,将有很多INSERTs 填充 10 列,并且有很多UPDATEs 填充剩余的列。

这张表上INSERTUPDATE语句的数量可能达到每秒数个。

由于一直发生大量锁定(由INSERTs 和UPDATEs引起),因此担心性能可能会成为问题,因为响应时间对于 Web 应用程序来说必须是合理的。

有人建议将该表拆分为另外 2 个表:一个包含首先插入的列,另一个包含将被更新的剩余列。

请记住,这将需要更复杂的对象关系映射,因为 OO 模型和所有文档都将其视为 1 个单个实体,而不是 2 个。

我的问题:

  • 这是一个很好的建议吗?你会考虑吗?有更好的方法吗?它会有所帮助吗?

或者

  • 这是男子气概的硬件问题吗?我应该为我的应用程序数据库建模而忽略这种优化并专注于使实体正确吗?我应该告诉硬件人员我需要更好的 I/O 吗?

如果缺少任何信息,请让我知道,并提前致谢。

Cad*_*oux 6

是的,这是一个有效的物理设计修改,以适应更灵活的锁定行为。

如果您加入两个表并使用视图将其公开给 ORM,我认为 ORM 不会知道其中的区别(除非它尝试查看视图元数据,例如在代码生成过程中寻找主键或其他内容)。

您的视图应该是可更新的,即使它不是由于可更新视图的某些特殊性限制,始终可以使用 INSTEAD OF 触发器进行更新

是的,我当然会考虑。在实际对单个表设计进行负载测试之前,我是否会考虑它,我不确定。

这是 SQL Server 中的示例:

CREATE TABLE main
( ID INT IDENTITY NOT NULL
 ,DATA VARCHAR(255)
 ,CONSTRAINT PK_MAIN PRIMARY KEY CLUSTERED (ID ASC)
 );

CREATE TABLE aux
( ID INT NOT NULL
 ,MOREDATA VARCHAR(255)
 ,CONSTRAINT PK_AUX PRIMARY KEY CLUSTERED (ID ASC)
 );

GO

CREATE VIEW unified
AS
  SELECT main.*, aux.MOREDATA
  FROM main
  INNER JOIN aux
    ON aux.ID = main.ID;
GO

INSERT INTO main (DATA) VALUES ('somedata');

INSERT INTO aux (ID, MOREDATA) VALUES (SCOPE_IDENTITY(), 'some more data');
Run Code Online (Sandbox Code Playgroud)

然后:

BEGIN TRANSACTION;

SELECT dm_tran_locks.request_session_id,
       dm_tran_locks.resource_database_id,
       DB_NAME(dm_tran_locks.resource_database_id) AS dbname,
       CASE
           WHEN resource_type = 'object'
               THEN OBJECT_NAME(dm_tran_locks.resource_associated_entity_id)
           ELSE OBJECT_NAME(partitions.OBJECT_ID)
       END AS ObjectName,
       partitions.index_id,
       indexes.name AS index_name,
       dm_tran_locks.resource_type,
       dm_tran_locks.resource_description,
       dm_tran_locks.resource_associated_entity_id,
       dm_tran_locks.request_mode,
       dm_tran_locks.request_status
FROM sys.dm_tran_locks
LEFT JOIN sys.partitions ON partitions.hobt_id = dm_tran_locks.resource_associated_entity_id
LEFT JOIN sys.indexes ON indexes.OBJECT_ID = partitions.OBJECT_ID AND indexes.index_id = partitions.index_id
WHERE resource_associated_entity_id > 0
  AND resource_database_id = DB_ID()
ORDER BY request_session_id, resource_associated_entity_id;

SELECT *
FROM unified;

UPDATE unified
SET MOREDATA = 'changed data'
WHERE ID = 1;

SELECT *
FROM unified;

SELECT dm_tran_locks.request_session_id,
       dm_tran_locks.resource_database_id,
       DB_NAME(dm_tran_locks.resource_database_id) AS dbname,
       CASE
           WHEN resource_type = 'object'
               THEN OBJECT_NAME(dm_tran_locks.resource_associated_entity_id)
           ELSE OBJECT_NAME(partitions.OBJECT_ID)
       END AS ObjectName,
       partitions.index_id,
       indexes.name AS index_name,
       dm_tran_locks.resource_type,
       dm_tran_locks.resource_description,
       dm_tran_locks.resource_associated_entity_id,
       dm_tran_locks.request_mode,
       dm_tran_locks.request_status
FROM sys.dm_tran_locks
LEFT JOIN sys.partitions ON partitions.hobt_id = dm_tran_locks.resource_associated_entity_id
LEFT JOIN sys.indexes ON indexes.OBJECT_ID = partitions.OBJECT_ID AND indexes.index_id = partitions.index_id
WHERE resource_associated_entity_id > 0
  AND resource_database_id = DB_ID()
ORDER BY request_session_id, resource_associated_entity_id;

COMMIT TRANSACTION;
Run Code Online (Sandbox Code Playgroud)