Réponses:
Pour SQL Server, vous pourriez faire valoir qu'une opération de validation n'est rien d'autre que l'écriture de LOP_COMMIT_XACT dans le fichier journal et la libération des verrous, ce qui va bien sûr être plus rapide que le ROLLBACK de chaque action effectuée par votre transaction depuis BEGIN TRAN.
Si vous envisagez chaque action d'une transaction, pas seulement la validation, je dirais toujours que votre déclaration n'est pas vraie. En excluant les facteurs externes, la vitesse du disque de journal par rapport à la vitesse du disque de données par exemple, il est probable que la restauration de tout travail effectué par une transaction soit plus rapide que d'effectuer le travail en premier lieu.
Une restauration consiste à lire un fichier séquentiel de modifications et à les appliquer aux pages de données en mémoire. Le «travail» d'origine devait générer un plan d'exécution, acquérir des pages, joindre des lignes, etc.
Edit: Le ça dépend un peu ...
@JackDouglas a signalé cet article qui décrit l'une des situations où la restauration peut prendre beaucoup plus de temps que l'opération d'origine. L'exemple étant une transaction de 14 heures, qui utilise inévitablement le parallélisme, il faut plus de 48 heures pour revenir en arrière, car la restauration est principalement à filetage unique. Vous seriez très probablement également en train de baratter le pool de tampons à plusieurs reprises, donc vous n'inversez plus les modifications apportées aux pages en mémoire.
Donc, une version révisée de ma réponse précédente. Le recul est-il beaucoup plus lent? Tout bien considéré, pour une transaction OLTP typique, ce n'est pas le cas. En dehors des limites du typique, cela peut prendre plus de temps pour "défaire" que "faire" mais (est-ce un tordement de langue potentiel?) Pourquoi dépendra de la façon dont le "faire" a été fait.
Edit2: Suite à la discussion dans les commentaires, voici un très artificiel exemple pour démontrer que le travail en cours est le facteur majeur pour déterminer les dépenses relatives de validation vs restauration en tant qu'opérations.
Créez deux tableaux et emballez-les de manière inefficace (espace perdu par page):
SET STATISTICS IO OFF;
SET STATISTICS TIME OFF;
SET NOCOUNT ON;
GO
CREATE TABLE dbo.Foo
(
col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
, col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)
CREATE TABLE dbo.Bar
(
col1 INT IDENTITY(1,1) PRIMARY KEY CLUSTERED
, col2 CHAR(4000) NOT NULL DEFAULT REPLICATE('A', 4000)
)
GO
INSERT dbo.Foo DEFAULT VALUES
GO 100000
INSERT dbo.Bar DEFAULT VALUES
GO 100000
Exécutez une "mauvaise" requête de mise à jour, en mesurant le temps nécessaire pour effectuer le travail et le temps nécessaire pour émettre la validation.
DECLARE
@StartTime DATETIME2
, @Rows INT
SET @Rows = 1
CHECKPOINT
DBCC DROPCLEANBUFFERS
BEGIN TRANSACTION
SET @StartTime = SYSDATETIME()
UPDATE
dbo.bar
SET
col2 = REPLICATE('B', 4000)
FROM
dbo.bar b
INNER JOIN
(
SELECT TOP(@Rows)
col1
FROM
dbo.foo
ORDER BY
NEWID()
) f
ON f.col1 = b.col1
OPTION (MAXDOP 1)
SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())
SET @StartTime = SYSDATETIME()
COMMIT TRANSACTION
SELECT 'Commit', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO
Faites de même, mais émettez et mesurez la restauration.
DECLARE
@StartTime DATETIME2
, @Rows INT
SET @Rows = 1
CHECKPOINT
DBCC DROPCLEANBUFFERS
BEGIN TRANSACTION
SET @StartTime = SYSDATETIME()
UPDATE
dbo.bar
SET
col2 = REPLICATE('B', 4000)
FROM
dbo.bar b
INNER JOIN
(
SELECT TOP(@Rows)
col1
FROM
dbo.foo
ORDER BY
NEWID()
) f
ON f.col1 = b.col1
OPTION (MAXDOP 1)
SELECT 'Find and update row', DATEDIFF(ms, @StartTime, SYSDATETIME())
SET @StartTime = SYSDATETIME()
ROLLBACK TRANSACTION
SELECT 'Rollback', DATEDIFF(ms, @StartTime, SYSDATETIME())
GO
Avec @ Rows = 1, j'obtiens un résultat raisonnablement cohérent:
Avec @ Rows = 100:
Avec @ Rows = 1000:
Retour à la question d'origine. Si vous mesurez le temps nécessaire pour effectuer le travail plus la validation, la restauration est gagnante car la majorité de ce travail est consacrée à la recherche de la ligne à mettre à jour, et non à la modification des données. Si vous examinez l'opération de validation de manière isolée, il doit être clair que la validation ne fonctionne que très peu en tant que telle. L'engagement est "J'ai fini".
begin tran
augmente simplement le compteur de transactions. Si je vous ai bien compris, rdbms fait toutes les tâches (jointures de lignes, génération de plans d'exécution ...) chez COMMIT?
Pour Oracle, la restauration peut prendre plusieurs fois plus de temps que le temps nécessaire pour effectuer les modifications qui sont annulées. Cela n'a souvent pas d'importance car
Pour SQL Server, je ne sais pas si la situation est la même, mais quelqu'un d'autre dira si ce n'est pas le cas ...
Quant au "pourquoi", je dirais que le rollback
devrait être rare , généralement seulement si quelque chose a mal tourné, et bien sûr commit
est probablement beaucoup plus courant - il est donc logique d'optimiser pourcommit
La restauration n'est pas seulement «oh, peu importe» - dans de nombreux cas, elle doit vraiment annuler ce qu'elle avait déjà fait. Il n'y a aucune règle selon laquelle l'opération de restauration sera toujours plus lente ou toujours plus rapide que l'opération d'origine, bien que même si la transaction d'origine s'est déroulée en parallèle, la restauration est monothread. Si vous attendez, je suggère qu'il est plus sûr de continuer à attendre.
Tout cela change avec SQL Server 2019, bien sûr, et la récupération de base de données accélérée (qui, à une pénalité également variable, permet une restauration instantanée quelle que soit la taille des données).
Toutes les transactions ne verront pas leur activité de validation bien meilleure que leur annulation. Un tel cas est l'opération de suppression dans SQL. Lorsqu'une transaction supprime des lignes, ces lignes sont marquées comme enregistrements fantômes. Une fois qu'un commit est émis et qu'une tâche de nettoyage des enregistrements fantômes démarre, seuls ces enregistrements sont «supprimés».
Si une restauration a été émise à la place, elle supprime simplement les marques fantômes de ces enregistrements, et non les instructions d'insertion intensives.
Pas tous. PostgreSQL ne prend pas plus de temps pour revenir en arrière que pour valider car les deux opérations sont effectivement identiques en termes d'E / S disque. Je ne pense pas que ce soit une question d'être optimisé pour la validation autant que de savoir pour quelles autres requêtes on optimise.
La question fondamentale est de savoir comment vous abordez la disposition sur le disque et comment cela affecte la validation par rapport à la restauration. Les bases de données principales qui annulent plus lentement que la validation ont tendance à déplacer les données, en particulier des tables en cluster, hors des structures de données principales et à les placer dans un segment d'annulation lors de la mise à jour des données. Cela signifie que pour vous engager, supprimez simplement le segment d'annulation, mais pour annuler, vous devez recopier toutes les données.
Pour PostgreSQL, toutes les tables sont des tables de tas et les index sont séparés. Cela signifie que lors de la restauration ou de la validation, aucune donnée ne doit être réorganisée. Cela rend la validation et la restauration rapides.
Cependant, cela ralentit certaines autres choses. Une recherche de clé primaire, par exemple, doit traverser un fichier d'index puis frapper la table de tas (en supposant qu'aucun index de couverture ne soit applicable). Ce n'est pas énorme, mais cela ajoute une recherche de page supplémentaire ou peut-être même quelques recherches de page aléatoires (si de nombreuses mises à jour se sont produites sur cette ligne) pour vérifier d'autres informations et visibilité.
La vitesse ici n'est cependant pas une question d'optimisation dans PostgreSQL pour les opérations d'écriture par rapport à celles de lecture. C'est une réticence à privilégier certaines opérations de lecture au-dessus d'autres. Par conséquent, PostgreSQL fonctionne en moyenne à peu près aussi bien que les autres bases de données. Ce ne sont que certaines opérations qui peuvent être plus rapides ou plus lentes.
Je pense donc que la réponse réelle est que les bases de données sont optimisées pour certaines charges de travail du côté lecture, ce qui entraîne des défis du côté écriture. Généralement, en cas de question, les validations sont généralement, mais pas toujours, privilégiées par rapport aux annulations. Cela dépend cependant des implications de l'une ou l'autre (les mises à jour sont différentes des suppressions).