Revision 644b730b
Von Moritz Bunkus vor mehr als 5 Jahren hinzugefügt
SL/BackgroundJob/SelfTest/Transactions.pm | ||
---|---|---|
631 | 631 |
my $query = qq| |
632 | 632 |
SELECT purpose from bank_transactions |
633 | 633 |
WHERE cleared is true |
634 |
AND id not in (SELECT bank_transaction_id from reconciliation_links)
|
|
634 |
AND NOT EXISTS (SELECT bank_transaction_id from reconciliation_links WHERE bank_transaction_id = bank_transactions.id)
|
|
635 | 635 |
AND transdate >= ? AND transdate <= ?|; |
636 | 636 |
|
637 | 637 |
my $bt_cleared_no_link = selectall_hashref_query($::form, $self->dbh, $query, $self->fromdate, $self->todate); |
... | ... | |
681 | 681 |
my $query = qq| |
682 | 682 |
SELECT purpose from bank_transactions |
683 | 683 |
WHERE invoice_amount <> 0 |
684 |
AND id not in (SELECT bank_transaction_id from bank_transaction_acc_trans)
|
|
684 |
AND NOT EXISTS (SELECT bank_transaction_id FROM bank_transaction_acc_trans WHERE bank_transaction_id = bank_transactions.id)
|
|
685 | 685 |
AND itime > (SELECT min(itime) from bank_transaction_acc_trans) |
686 | 686 |
AND transdate >= ? AND transdate <= ?|; |
687 | 687 |
|
... | ... | |
701 | 701 |
SELECT purpose from bank_transactions |
702 | 702 |
WHERE id in |
703 | 703 |
(SELECT bank_transaction_id from bank_transaction_acc_trans |
704 |
where acc_trans_id NOT IN (select acc_trans_id from acc_trans)
|
|
704 |
WHERE NOT EXISTS (SELECT acc_trans.acc_trans_id FROM acc_trans WHERE acc_trans.acc_trans_id = bank_transaction_acc_trans.acc_trans_id)
|
|
705 | 705 |
AND transdate >= ? AND transdate <= ?)|; |
706 | 706 |
|
707 | 707 |
my $bt_assigned_no_acc_trans = selectall_hashref_query($::form, $self->dbh, $query, $self->fromdate, $self->todate); |
Auch abrufbar als: Unified diff
SelfTest: Geschwindigkeitssteigerung durch »NOT EXISTS« anstelle von »NOT IN«
Nicht ganz frische PostgreSQL-Versionen (mindestens bis 9.6 inklusive)
optimieren »NOT IN«-mit-Subquery nicht automatisch und müssen daher
für jede Zeile des äußeren Selects einen linearen Scan auf die
Subquery-Tabelle machen.
Deutlich effektiver ist das in diesem Fall äquivalente »NOT
EXISTS«-mit-Subquery.
Beispiel: Namen aller Kunden, für die noch keine Rechnung geschrieben
wurde. Falsch mit »NOT IN«:
SELECT name
FROM customer
WHERE id NOT IN (
SELECT customer_id
FROM ar
);
Besser und semantisch äquivalent:
SELECT name
FROM customer
WHERE NOT EXISTS (
SELECT customer_id
FROM ar
WHERE customer_id = customer.id
);
Geschwindigkeitssteigerung ist auch ein Euphemismus. Vor der Änderung
war der Selftest bei der LINET-Produktivdatenbank nicht in der Lage,
seine Tests innerhalb von drei Tagen auszuführen. Nach der Änderung
dauert der Selftest weniger als eine Minute.
Neure PostgreSQL-Versionen (z.B. v11) erkennen dieses Pattern
automatisch.