sql >> Database >  >> RDS >> Mysql

JOIN vs. WHERE:Waarom vertonen twee zoekopdrachten die identieke resultaten opleveren 3-4 ordes van grootte prestatieverschil?

MySQL heeft bekende problemen met het optimaliseren van zoekopdrachten met gecorreleerde subquery's of subselecties. Tot versie 5.6.5 worden er geen subquery's gegenereerd, maar het zal een afgeleide tabel opleveren die in een join wordt gebruikt.

In wezen betekent dit dat wanneer u een join gebruikt, de eerste keer dat de subquery wordt aangetroffen, MySQL het volgende zal uitvoeren:

SELECT code1 FROM myTable GROUP BY code1 HAVING COUNT(code1) > 1

En bewaar de resultaten in een tijdelijke tabel (die is gehasht om zoekopdrachten sneller te laten verlopen), en vervolgens voor elke waarde in myTable het zal opzoeken in de tijdelijke tabel om te zien of de code daar is.

Echter, sinds wanneer u IN . gebruikt de subquery is niet gerealiseerd en is herschreven als:

SELECT t1.code1, t1.code2
FROM myTable t1
WHERE EXISTS
    (   SELECT t2.code1 
        FROM myTable t2
        WHERE t2.Code1 = t1.Code1
        GROUP BY t2.code1 
        HAVING COUNT(t2.code1) > 1
    )

Wat betekent dat voor elke code in myTable , wordt de subquery opnieuw uitgevoerd. Wat prima is als uw buitenste query erg smal is, omdat het efficiënter is om de subquery slechts een paar keer uit te voeren, dan om deze voor alle waarden uit te voeren en de resultaten op te slaan in een tijdelijke tabel, maar wanneer uw buitenste query breed is, resulteert dit in in de innerlijke query die vele malen wordt uitgevoerd, en dit is waar het prestatieverschil begint.

Dus voor uw rijtellingen, in plaats van de subquery ~ 30.000 keer uit te voeren, voert u deze één keer uit en zoekt u vervolgens ~ 30.000 rijen op in een gehashte tijdelijke tabel met slechts 400 rijen erin. Dit zou zo'n drastisch prestatieverschil verklaren.

Dit artikel in de online documenten legt de optimalisatie van subquery's veel dieper uit.




  1. C#:Oracle Data Type Equivalentie met OracleDbType

  2. Best practices voor PostgreSQL-beveiliging

  3. Hoe MySQL JDBC 08001 Databaseverbindingsfout op te lossen?

  4. Een msdb-gebruikerstoegang verlenen tot een database-e-mailprofiel in SQL Server (T-SQL)