Mysql databse , bij minder dan 2 identieke waardes de rij verwijderen
Als dit artiekel 1 keer voorkomt, wil ik de rijen verwidjeren, dus ik doe:
Code (php)
1
2
3
4
5
2
3
4
5
$deld = mysqli_query($DBD->conn(),"SELECT *, count(ean) as TEL FROM `pro_pr_spec` group by ean HAVING count(*) = 1") or die (mysqli_error($DBD->conn()));
while ($ppp = mysqli_fetch_array($deld))
{
$th = mysqli_query($DBD->conn(),"DELETE FROM pro_pr_spec WHERE pid = '".$ppp['pid']."'") or die (mysqli_error($DBD->conn()));
}
while ($ppp = mysqli_fetch_array($deld))
{
$th = mysqli_query($DBD->conn(),"DELETE FROM pro_pr_spec WHERE pid = '".$ppp['pid']."'") or die (mysqli_error($DBD->conn()));
}
Dit werkt wel, maar gewoon veels te langzaam, terwijl ik de kolommen geindexeert heb.
Ik er een manier om dit sneller te laten werken?
Gewijzigd op 28/07/2019 15:37:40 door - Ariën -
En dit zou je vervolgens in een subquery kunnen stoppen, zodat je maar 1 query nodig hebt, in plaats van een loop. Maar ook dat moet je op de juiste manier doen. Mogelijk kun je de volgende constructie gebruiken.
Als er een loop in je code staan waarbinnen queries worden uitgevoerd, dan is dit in ieder geval vaak een indicatie dat er iets mis is.
Het was zo langaam,met name door te weinig indexen.
Daarna ging het een stuk sneller.
Is een single query sneller dat deze wijze?
Bedankt
Op het moment dat code een loop bevat met daarin een query-aanroep, dan heeft dat het potentiële gevaar dat op den duur het totaal aantal queries (explosief) oploopt als de loop -om wat voor reden dan ook- langer wordt. Dit kan vervolgens weer een sneeuwbaleffect veroorzaken op het moment dat meerdere gebruikers een pagina met een dergelijke aanpak opvragen. Deze constructie is dus niet goed schaalbaar. Daarom zou je dit te allen tijde moeten vermijden en zou er een alarmbel moeten gaan rinkelen als je dit ergens tegenkomt.
En uiteraard kosten minder queries altijd (per definitie :p) minder tijd. Dit neemt niet weg dat je queries altijd op efficiëntie zou moeten testen. Er hoeft namelijk maar één brakke query tussen te zitten en dat maakt dan alles traag.
Misschien is het voor de kijkers thuis ook interessant om te vertellen welke query hier uiteindelijk is uitgerold, met misschien een kanttekening over eventueel toegevoegde indexes of andere structuurwijzigingen die je hebt aangebracht.
Dat zou iets moeten zijn als
>> alle kolommen die niet in de aggregatie functie(s) staan, horen in GROUP BY genoemd te worden. "SELECT *" in combi met GROUP BY is vrijwel altijd fout. Al klaagt Mysql pas als je hem wat strikter dan default instelt.
Ten tweede:
dit zou ook in 1 query kunnen.
Bijvoorbeeld:
Code (php)
1
2
3
4
5
6
7
2
3
4
5
6
7
DELETE FROM pro_pr_spec
WHERE ean IN (
SELECT ean
FROM pro_pr_spec
GROUP BY ean
HAVING COUNT(1) = 1
)
WHERE ean IN (
SELECT ean
FROM pro_pr_spec
GROUP BY ean
HAVING COUNT(1) = 1
)
Al ben ik geen fan van deze constructie: veel waarden in het stukje "in (subquery)" maakt het traag.
bovendien wil mysql dat in tegenstelling tot andere databases niet doen, omdat gelijktijdig geselecteerd en aangepast wordt op 1 query. Een Temp table zou dan uitkomt brengen.
Mooiste is echter een join:
Code (php)
1
2
3
4
2
3
4
DELETE pro_pr_spec FROM pro_pr_spec
JOIN (SELECT ean
FROM pro_pr_spec GROUP BY ean HAVING COUNT(1) = 1) AS magweg
ON pro_pr_spec .ean = magweg.ean
JOIN (SELECT ean
FROM pro_pr_spec GROUP BY ean HAVING COUNT(1) = 1) AS magweg
ON pro_pr_spec .ean = magweg.ean
Een index op EAN zou dan nuttig kunnen zijn.