哪种方法在数据库性能方面更好 - 一个 table 组操作或多个 table 可序列化事务?
Which approach is better in terms of database performance - one table group by operations or multiple tables serializable transaction?
我正在开发一个基于 SQL 数据库的预订系统(对特定数据库没有限制)。
架构:
工作流程:
现在我正在使用一个特殊的 'actual_reservations' 视图,该视图基于带有过滤逻辑的自定义分组依据来识别实际放置的预订,例如:
CREATE VIEW `reserv-io`.`actual_reserved_resources` AS
SELECT
`r`.`id`,
`a`.`resource_id`,
`a`.`type_id`,
`a`.`status_id`,
`a`.`reservation_start`,
`a`.`reservation_end`
FROM `reserv-io`.`actions` `a`
JOIN (SELECT
`r`.`id` `id`,
MAX(`a`.`id`) `action_id`
FROM `reserv-io`.`reservations` `r`
JOIN `reserv-io`.`actions` `a` ON `r`.`id` = `a`.`reservation_id`
WHERE (`r`.`id` NOT IN
(SELECT `r`.`id` `id`
FROM `reserv-io`.`reservations` `r`
JOIN `reserv-io`.`actions` `a` ON `r`.`id` = `a`.`reservation_id`
WHERE (`a`.`status_id` IN
(SELECT `id`
FROM `reserv-io`.`reservation_statuses`
WHERE `name` = 'Canceled')))
AND `a`.`status_id` IN
(SELECT `id`
FROM `reserv-io`.`reservation_statuses`
WHERE `name` = 'Approved' OR `name` = 'Accepted'))
GROUP BY `r`.`id`) `b`
ON `a`.`id` = `b`.`action_id`
JOIN `reserv-io`.`reservations` `r` ON `r`.`id` = `a`.`reservation_id`;
并确定是否与其他预订有任何重叠,过程如下:
CREATE PROCEDURE HAS_OVERLAPPING_RESERVATION_WITH_TYPE_SELF_CHECK(
IN RESERVATION BIGINT,
IN RESOURCE INT,
IN RESERVATION_TYPE INT,
IN STARTS_AT DATETIME,
IN ENDS_AT DATETIME,
OUT RESULT BIT)
BEGIN
SELECT CASE WHEN EXISTS(
SELECT *
FROM actual_reserved_resources r
WHERE r.resource_id = RESOURCE
AND r.type_id = RESERVATION_TYPE
AND r.reservation_start < ENDS_AT
AND r.reservation_end > STARTS_AT
AND r.id <> RESERVATION)
THEN TRUE
ELSE FALSE END
INTO RESULT;
END$$
我在 'actions' table 上已经有了很好的索引,但我不确定我对与预订相关的所有操作使用单个 table 的方法是否真的具有可扩展性。我听说过一种方法,我将所有待定和实际批准的预订存储在单独的 table 中,然后手动将它们同步到交易中。
我的问题是,在数据库性能、可伸缩性和良好的数据设计方面,您的 POV 中的哪种方法更好?
我建议:
不要想当然地接受任何人的回答;相反,使用真实世界的数据进行基准测试,以衡量实际性能。
无论答案是什么,都没有你担心的那么重要。它肯定不会区分可扩展系统和不可扩展系统。
如果事实证明将某种记录分为待处理和已批准的记录实际上有任何优点,您将能够通过行分区(查找)这样您就可以将所有内容保持在一个逻辑中 table 并避免以性能的名义搞乱您的架构。
您没有提及您的数据集的大小或您要运行查询的系统的大小。在您获得大型数据集之前,它可能没有太大区别。我对大型数据集的个人经验是,当系统开始换出到磁盘而不是将内容保存在内存中时,跨两个以上表的连接执行起来会非常慢。几年前在 Oracle 上,我有一个特定的查询需要涉及六个表。在一次查询中,运行 花了大约六个小时。由于单个查询同时涉及两个表,因此需要 15 分钟。我对 MySQL 有一个不同的查询,它涉及一些表。将其分解为更小的查询可将总 运行 时间从大约 7 小时减少到 7 分钟。
我正在开发一个基于 SQL 数据库的预订系统(对特定数据库没有限制)。
架构:
工作流程:
现在我正在使用一个特殊的 'actual_reservations' 视图,该视图基于带有过滤逻辑的自定义分组依据来识别实际放置的预订,例如:
CREATE VIEW `reserv-io`.`actual_reserved_resources` AS
SELECT
`r`.`id`,
`a`.`resource_id`,
`a`.`type_id`,
`a`.`status_id`,
`a`.`reservation_start`,
`a`.`reservation_end`
FROM `reserv-io`.`actions` `a`
JOIN (SELECT
`r`.`id` `id`,
MAX(`a`.`id`) `action_id`
FROM `reserv-io`.`reservations` `r`
JOIN `reserv-io`.`actions` `a` ON `r`.`id` = `a`.`reservation_id`
WHERE (`r`.`id` NOT IN
(SELECT `r`.`id` `id`
FROM `reserv-io`.`reservations` `r`
JOIN `reserv-io`.`actions` `a` ON `r`.`id` = `a`.`reservation_id`
WHERE (`a`.`status_id` IN
(SELECT `id`
FROM `reserv-io`.`reservation_statuses`
WHERE `name` = 'Canceled')))
AND `a`.`status_id` IN
(SELECT `id`
FROM `reserv-io`.`reservation_statuses`
WHERE `name` = 'Approved' OR `name` = 'Accepted'))
GROUP BY `r`.`id`) `b`
ON `a`.`id` = `b`.`action_id`
JOIN `reserv-io`.`reservations` `r` ON `r`.`id` = `a`.`reservation_id`;
并确定是否与其他预订有任何重叠,过程如下:
CREATE PROCEDURE HAS_OVERLAPPING_RESERVATION_WITH_TYPE_SELF_CHECK(
IN RESERVATION BIGINT,
IN RESOURCE INT,
IN RESERVATION_TYPE INT,
IN STARTS_AT DATETIME,
IN ENDS_AT DATETIME,
OUT RESULT BIT)
BEGIN
SELECT CASE WHEN EXISTS(
SELECT *
FROM actual_reserved_resources r
WHERE r.resource_id = RESOURCE
AND r.type_id = RESERVATION_TYPE
AND r.reservation_start < ENDS_AT
AND r.reservation_end > STARTS_AT
AND r.id <> RESERVATION)
THEN TRUE
ELSE FALSE END
INTO RESULT;
END$$
我在 'actions' table 上已经有了很好的索引,但我不确定我对与预订相关的所有操作使用单个 table 的方法是否真的具有可扩展性。我听说过一种方法,我将所有待定和实际批准的预订存储在单独的 table 中,然后手动将它们同步到交易中。
我的问题是,在数据库性能、可伸缩性和良好的数据设计方面,您的 POV 中的哪种方法更好?
我建议:
不要想当然地接受任何人的回答;相反,使用真实世界的数据进行基准测试,以衡量实际性能。
无论答案是什么,都没有你担心的那么重要。它肯定不会区分可扩展系统和不可扩展系统。
如果事实证明将某种记录分为待处理和已批准的记录实际上有任何优点,您将能够通过行分区(查找)这样您就可以将所有内容保持在一个逻辑中 table 并避免以性能的名义搞乱您的架构。
您没有提及您的数据集的大小或您要运行查询的系统的大小。在您获得大型数据集之前,它可能没有太大区别。我对大型数据集的个人经验是,当系统开始换出到磁盘而不是将内容保存在内存中时,跨两个以上表的连接执行起来会非常慢。几年前在 Oracle 上,我有一个特定的查询需要涉及六个表。在一次查询中,运行 花了大约六个小时。由于单个查询同时涉及两个表,因此需要 15 分钟。我对 MySQL 有一个不同的查询,它涉及一些表。将其分解为更小的查询可将总 运行 时间从大约 7 小时减少到 7 分钟。