2 votes

Grande différence de temps pour supprimer des tables temporaires postgres

J'avais une requête qui prenait beaucoup de temps à s'exécuter. Je l'ai donc réécrite et maintenant elle ne prend presque pas de temps à s'exécuter - mais je ne comprends pas pourquoi.

Je peux comprendre une petite différence, mais quelqu'un peut-il m'aider à expliquer l'énorme différence de temps nécessaire pour exécuter ces deux déclarations (qui semblent très similaires) ?

D'abord :

DELETE FROM     t_old where company_id not in (select company_id from t_prop);

Deuxièmement :

DELETE FROM     t_old a
using           t_prop b 
where           a.company_id=b.company_id
and             b.company_id is null;

Plan d'exécution du premier :

'[
  {
    "Plan": {
  "Startup Cost": 0,
  "Plans": [
    {
      "Filter": "(NOT (SubPlan 1))",
      "Startup Cost": 0,
      "Plans": [
        {
          "Startup Cost": 0,
          "Plans": [
            {
              "Startup Cost": 0,
              "Node Type": "Seq Scan",
              "Plan Rows": 158704,
              "Relation Name": "t_prop",
              "Alias": "t_prop",
              "Parallel Aware": false,
              "Parent Relationship": "Outer",
              "Plan Width": 4,
              "Total Cost": 2598.04
            }
          ],
          "Node Type": "Materialize",
          "Plan Rows": 158704,
          "Parallel Aware": false,
          "Parent Relationship": "SubPlan",
          "Plan Width": 4,
          "Subplan Name": "SubPlan 1",
          "Total Cost": 4011.56
        }
      ],
      "Node Type": "Seq Scan",
      "Plan Rows": 21760,
      "Relation Name": "t_old",
      "Alias": "t_old",
      "Parallel Aware": false,
      "Parent Relationship": "Member",
      "Plan Width": 6,
      "Total Cost": 95923746.03
    }
  ],
  "Node Type": "ModifyTable",
  "Plan Rows": 21760,
  "Relation Name": "t_old",
  "Alias": "t_old",
  "Parallel Aware": false,
  "Operation": "Delete",
  "Plan Width": 6,
  "Total Cost": 95923746.03
}

} ]'

Plan d'exécution du second

'[
  {
    "Plan": {
      "Startup Cost": 0.71,
      "Plans": [
        {
          "Startup Cost": 0.71,
          "Plans": [
            {
              "Startup Cost": 0.42,
              "Scan Direction": "Forward",
              "Plan Width": 10,
              "Node Type": "Index Scan",

          "Index Cond": "(company_id IS NULL)",
          "Plan Rows": 1,
          "Relation Name": "t_prop",
          "Alias": "b",
          "Parallel Aware": false,
          "Parent Relationship": "Outer",
          "Total Cost": 8.44,
          "Index Name": "t_prop_idx2"
        },
        {
          "Startup Cost": 0.29,
          "Scan Direction": "Forward",
          "Plan Width": 10,
          "Node Type": "Index Scan",
          "Index Cond": "(company_id = b.company_id)",
          "Plan Rows": 5,
          "Relation Name": "t_old",
          "Alias": "a",
          "Parallel Aware": false,
          "Parent Relationship": "Inner",
          "Total Cost": 8.38,
          "Index Name": "t_old_idx"
        }
      ],
      "Node Type": "Nested Loop",
      "Plan Rows": 5,
      "Join Type": "Inner",
      "Parallel Aware": false,
      "Parent Relationship": "Member",
      "Plan Width": 12,
      "Total Cost": 16.86
    }
  ],
  "Node Type": "ModifyTable",
  "Plan Rows": 5,
  "Relation Name": "t_old",
  "Alias": "a",
  "Parallel Aware": false,
  "Operation": "Delete",
  "Plan Width": 12,
  "Total Cost": 16.86
}

} ]'

1voto

Łukasz Kamiński Points 3364

Votre deuxième requête ne supprimera rien, c'est pourquoi elle est beaucoup plus rapide.

EDIT : Je suppose que je devrais expliquer pourquoi il ne supprime rien. Donc...

Ce que vous vouliez faire est en fait ceci :

DELETE FROM     t_old a
using           t_old a2
LEFT JOIN       t_prop b ON b.company_id = a2.company_id
where           a.company_id=a2.company_id
and             b.company_id is null;

Elle peut être plus rapide, plus lente ou égale à la vitesse de votre première requête, mais elle fera la même chose.

Cependant, votre deuxième requête ne supprimera que les rangées de t_old s'il y a également des lignes dans t_prop avec l'assortiment company_id parce que vous faites INNER JOIN là-dedans. Mais il y a aussi une condition supplémentaire b.company_id is null avec limitera en plus les rangs dans t_prop à ceux qui ont cette colonne égale à NULL pero = L'opérateur ne fonctionne pas pour NULL et ne seront jamais évaluées à true Ainsi, votre première condition échouera toujours si vous parvenez à satisfaire la seconde. Considérant qu'il y a AND entre eux, les deux doivent être satisfaits, ce qui est impossible.

Ce qui pourrait fonctionner et supprimerait des lignes dans t_old WHERE company_id IS NULL qui sont aussi dans t_prop avec la même condition satisfaite est que :

DELETE FROM     t_old a
using           t_prop b 
where           a.company_id IS NOT DISTINCT FROM b.company_id
and             b.company_id is null;

Mais ça ne ferait toujours pas ce que la première requête fait.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X