Mysql databse , bij minder dan 2 identieke waardes de rij verwijderen

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Daniel van Seggelen

Daniel van Seggelen

28/07/2019 15:10:32
Quote Anchor link
Ik heb een table waarin prijzen staan met meerdere artikelnummers (ean codes).

Als dit artiekel 1 keer voorkomt, wil ik de rijen verwidjeren, dus ik doe:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
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()));    
}


Dit werkt wel, maar gewoon veels te langzaam, terwijl ik de kolommen geindexeert heb.

Ik er een manier om dit sneller te laten werken?
 
PHP hulp

PHP hulp

20/04/2024 18:39:24
 
- Ariën  -
Beheerder

- Ariën -

28/07/2019 15:36:03
Quote Anchor link
Hoe langzaam? Hoe is die table opgebouwd, en welke engine?
Gewijzigd op 28/07/2019 15:37:40 door - Ariën -
 
Thomas van den Heuvel

Thomas van den Heuvel

28/07/2019 15:46:25
Quote Anchor link
Heb je al eens een EXPLAIN op beide queries gedaan, zodat je precies kunt bepalen wat er zoveel tijd kost? Mogelijk is het de count(*)? Waarom gebruik je dat? Je hoeft ook niet alles te selecteren, enkel een id is genoeg? Je zou dus beter COUNT(<id_veld>) AS aantal kunnen gebruiken? En vervolgens simpelweg HAVING aantal = 1 kunnen gebruiken.

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.
 
Daniel van Seggelen

Daniel van Seggelen

29/07/2019 02:56:20
Quote Anchor link
Bedankt,

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
 
Thomas van den Heuvel

Thomas van den Heuvel

29/07/2019 14:26:28
Quote Anchor link
Queries zijn relatief dure operaties. Dus hoe minder hoe beter.

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.
 
Ivo P

Ivo P

01/08/2019 15:52:16
Quote Anchor link
ten eerste denk ik dat de query niet helemaal klopt:

Dat zou iets moeten zijn als

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
SELECT ean
FROM pro_pr_spec
GROUP BY ean
HAVING COUNT(1) = 1


>> 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)
PHP script in nieuw venster Selecteer het PHP script
1
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
)


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)
PHP script in nieuw venster Selecteer het PHP script
1
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


Een index op EAN zou dan nuttig kunnen zijn.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.