Slome query tussen twee databases

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • PaulEm
  • Registratie: Januari 2008
  • Laatst online: 03-02 07:52
Tot op heden heeft de onderstaande query normaal gefunctioneerd, echter neemt deze nu bijna zo'n 3 minuten in.

SQL:
1
2
3
4
5
6
7
8
9
SELECT d.*,
       a.*
FROM   icecat_data d
       LEFT JOIN artikeldata.artikels a
              ON Trim(a.a_reflev) = d.product_id
WHERE  d.data IS NOT NULL
       AND d.invalid = 0
       AND d.pending = 1
ORDER  BY a.a_artstat DESC


Trim op a_reflev is nodig omdat de data die in deze tabel gedumped wordt standaard een X-aantal spaties bevat. Deze data is niet in eigen beheer dus valt niet op te lossen. Wanneer ik de tabel tijdelijk een update geef met trim(a_reflev) en deze vervolgens achterwege laat in de query maakt dit verder geen performance verschil.

Een explain geeft mij het volgende terug:
idselect_typetabletypepossible_keyskeykey_lenrefrowsExtra
1SIMPLEdALLNULLNULLNULLNULL1400Using where; Using temporary; Using filesort
1SIMPLEaALLNULLNULLNULLNULL17415


Dit is de structuur van de tabellen:
SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
CREATE TABLE IF NOT EXISTS `icecat_data` (
  `id` int(9) NOT NULL AUTO_INCREMENT,
  `date_created` datetime NOT NULL,
  `date_updated` datetime NOT NULL,
  `product_id` varchar(30) NOT NULL,
  `vendor` varchar(25) NOT NULL,
  `data` mediumtext,
  `pending` tinyint(1) NOT NULL DEFAULT '1',
  `invalid` tinyint(1) NOT NULL DEFAULT '0',
  `removed` tinyint(1) NOT NULL DEFAULT '0',
  PRIMARY KEY (`id`),
  UNIQUE KEY `product_id` (`product_id`,`vendor`),
  KEY `product_id_2` (`product_id`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8;


SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
CREATE TABLE IF NOT EXISTS `artikels` (
  `a_stuknr` varchar(30) NOT NULL DEFAULT '0',
  `a_sorteer` float(8,3) NOT NULL,
  `a_lveld1` tinyint(1) NOT NULL DEFAULT '0',
  `e_lveld1` tinyint(1) NOT NULL DEFAULT '0',
  `a_lveld2` tinyint(1) NOT NULL DEFAULT '0',
  `a_lveld3` tinyint(1) NOT NULL DEFAULT '0',
  `a_lveld4` tinyint(1) NOT NULL DEFAULT '0',
  `a_type` varchar(20) NOT NULL DEFAULT '',
  `a_volgnr` varchar(20) NOT NULL DEFAULT '0',
  `a_nummer` varchar(20) NOT NULL DEFAULT '',
  `a_reflev` varchar(50) NOT NULL DEFAULT '',
  `a_folder` tinyint(1) NOT NULL DEFAULT '0',
  `a_fprijsd` float(8,3) NOT NULL DEFAULT '0.000',
  `a_fprijsm` float(8,3) NOT NULL DEFAULT '0.000',
  `a_fdatum` date NOT NULL DEFAULT '0000-00-00',
  `a_fvdatum` date NOT NULL DEFAULT '0000-00-00',
  `a_fprijsi` float(8,3) NOT NULL DEFAULT '0.000',
  `a_groep` char(3) NOT NULL DEFAULT '',
  `a_merkid` smallint(3) NOT NULL DEFAULT '0',
  `a_minverk` float(8,3) NOT NULL DEFAULT '0.000',
  `a_omschrn` varchar(250) NOT NULL DEFAULT '',
  `a_omschrf` varchar(200) NOT NULL DEFAULT '',
  `recupeurex` float(8,3) NOT NULL DEFAULT '0.000',
  `a_soort` char(3) NOT NULL DEFAULT '',
  `a_artstat` char(1) NOT NULL DEFAULT '',
  `a_instock` smallint(5) NOT NULL DEFAULT '0',
  `a_bokl` tinyint(5) NOT NULL DEFAULT '0',
  `a_bolv` tinyint(5) NOT NULL DEFAULT '0',
  `a_verdat` date NOT NULL DEFAULT '0000-00-00',
  `e_instock` smallint(5) NOT NULL,
  `e_bokl` tinyint(5) NOT NULL,
  `e_bolv` tinyint(5) NOT NULL,
  `g_bokl` tinyint(5) NOT NULL,
  `g_bolv` tinyint(5) NOT NULL,
  `g_verdat` date NOT NULL,
  `l_instock` smallint(5) NOT NULL,
  `l_bokl` tinyint(5) NOT NULL,
  `l_bolv` tinyint(5) NOT NULL,
  `l_verdat` date NOT NULL,
  `m_instock` smallint(5) NOT NULL,
  `m_bokl` tinyint(5) NOT NULL,
  `m_bolv` tinyint(5) NOT NULL,
  `m_verdat` date NOT NULL,
  `d_instock` smallint(5) NOT NULL,
  `d_bokl` tinyint(5) NOT NULL,
  `d_bolv` tinyint(5) NOT NULL,
  `d_verdat` date NOT NULL,
  `s_instock` smallint(5) NOT NULL,
  `s_bokl` tinyint(5) NOT NULL,
  `s_bolv` tinyint(5) NOT NULL,
  `s_verdat` date NOT NULL,
  `u_instock` smallint(5) NOT NULL,
  `u_bokl` tinyint(5) NOT NULL,
  `u_bolv` tinyint(5) NOT NULL,
  `u_verdat` date NOT NULL,
  `a_nomstock` smallint(5) NOT NULL DEFAULT '0',
  `a_aanbevol` float(8,3) NOT NULL DEFAULT '0.000',
  `a_basisex` float(8,3) NOT NULL DEFAULT '0.000',
  `a_dealer` float(8,3) NOT NULL DEFAULT '0.000',
  `a_winkel` float(8,3) NOT NULL DEFAULT '0.000',
  `a_winex` float(8,3) NOT NULL DEFAULT '0.000',
  `a_fprijs` float(8,3) NOT NULL DEFAULT '0.000',
  `a_btwcode` smallint(5) NOT NULL DEFAULT '0',
  `e_verdat` date NOT NULL,
  `g_instock` smallint(5) NOT NULL,
  `a_cveld6` char(20) DEFAULT NULL,
  `last_update_stock` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP,
  `last_update_article` datetime DEFAULT NULL,
  `Reprobelex` float(8,3) DEFAULT NULL,
  `Auvibelex` float(8,3) DEFAULT NULL,
  `Bebatex` float(8,3) DEFAULT NULL,
  `recupelex` float(8,3) DEFAULT NULL,
  `b_instock` smallint(5) NOT NULL,
  `b_bokl` tinyint(5) NOT NULL,
  `b_bolv` tinyint(5) NOT NULL,
  `b_verdat` date NOT NULL,
  `c_instock` smallint(5) NOT NULL,
  `c_bokl` tinyint(5) NOT NULL,
  `c_bolv` tinyint(5) NOT NULL,
  `c_verdat` date NOT NULL,
  `f_instock` smallint(5) NOT NULL,
  `f_bokl` tinyint(5) NOT NULL,
  `f_bolv` tinyint(5) NOT NULL,
  `f_verdat` date NOT NULL,
  `h_instock` smallint(5) NOT NULL,
  `h_bokl` tinyint(5) NOT NULL,
  `h_bolv` tinyint(5) NOT NULL,
  `h_verdat` date NOT NULL,
  PRIMARY KEY (`a_nummer`),
  KEY `a_groep` (`a_groep`),
  KEY `a_merkid` (`a_merkid`),
  KEY `a_soort` (`a_soort`),
  KEY `a_volgnr` (`a_volgnr`),
  KEY `a_reflev` (`a_reflev`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;


Indexes zijn toegevoegd aan a_reflev en product_id. De data verwerken vanuit twee aparte queries wordt vrijwel onmogelijk, PHP heeft het namelijk best zwaar om 17k rijen van artikeldata te verwerken. Heeft iemand nog tips om deze query te optimaliseren?

Acties:
  • 0 Henk 'm!

  • Woy
  • Registratie: April 2000
  • Niet online

Woy

Moderator Devschuur®
Ik heb je post niet echt goed gelezen, dus heb geen idee wat het probleem exact is, maar het eerste wat me opvalt is de gekke join die je hebt
SQL:
1
ON Trim(a.a_reflev) = d.product_id 

Waarom doe je een join op een ID met een waarde die je moet TRIMMEN? Dat lijkt me verdacht.

Verder is het natuurlijk ook een kwestie van de juiste indexen toevoegen, want die zie ik nu niet terug komen op de velden waarvoor dat logisch zou zijn.
Niet goed gekeken. Maar ik neem aan dat de index niet gebruikt wordt door de TRIM

[ Voor 30% gewijzigd door Woy op 29-06-2012 10:17 ]

“Build a man a fire, and he'll be warm for a day. Set a man on fire, and he'll be warm for the rest of his life.”


Acties:
  • 0 Henk 'm!

  • TheNephilim
  • Registratie: September 2005
  • Laatst online: 17-09 11:07

TheNephilim

Wtfuzzle

Woy schreef op vrijdag 29 juni 2012 @ 10:15:
Ik heb je post niet echt goed gelezen, dus heb geen idee wat het probleem exact is, maar het eerste wat me opvalt is de gekke join die je hebt
SQL:
1
ON Trim(a.a_reflev) = d.product_id 

Waarom doe je een join op een ID met een waarde die je moet TRIMMEN? Dat lijkt me verdacht.

Verder is het natuurlijk ook een kwestie van de juiste indexen toevoegen, want die zie ik nu niet terug komen op de velden waarvoor dat logisch zou zijn.
Niet goed gekeken. Maar ik neem aan dat de index niet gebruikt wordt door de TRIM
`a_reflev` varchar(50) NOT NULL DEFAULT '',

Volgens mij moet je die even casten naar INT in je JOIN. Misschien gaat het dan goed?

[ Voor 4% gewijzigd door TheNephilim op 29-06-2012 10:19 ]


Acties:
  • 0 Henk 'm!

  • CodeCaster
  • Registratie: Juni 2003
  • Niet online

CodeCaster

Can I get uhm...

PaulEm schreef op vrijdag 29 juni 2012 @ 10:02:
Tot op heden heeft de onderstaande query normaal gefunctioneerd, echter neemt deze nu bijna zo'n 3 minuten in.
Ik ken geen bug die specifiek vandaag getriggerd wordt in MySQL, dus wellicht is er aan de situatie iets veranderd? Heb je ineens veel meer data, is er veel meer verkeer over het netwerk?

Verder is je datamodel verre van optimaal, maar daar zul je op dit moment weinig aan kunnen doen. Lees eens iets over normalisatie. :)

https://oneerlijkewoz.nl
Op papier is hij aan het tekenen, maar in de praktijk...


Acties:
  • 0 Henk 'm!

  • Devil
  • Registratie: Oktober 2001
  • Niet online

Devil

King of morons

Kun je geen trigger maken die a.a_reflev automatisch trimmed op insert?
Verder een beetje experimenteren met het maken van indexes. Hou er rekening mee dat er voor elke component die je bij de 'explain' ziet maar 1 index gebruikt kan worden. Vooral op tabel a kun je waarschijnlijk flink wat performance winst halen met bijvoorbeel een key op revlev en artstat.

Ik zou daar een beetje mee experimenteren.

After all, we are nothing more or less than what we choose to reveal.


Acties:
  • 0 Henk 'm!

  • PaulEm
  • Registratie: Januari 2008
  • Laatst online: 03-02 07:52
Woy schreef op vrijdag 29 juni 2012 @ 10:15:
Ik heb je post niet echt goed gelezen, dus heb geen idee wat het probleem exact is, maar het eerste wat me opvalt is de gekke join die je hebt
SQL:
1
ON Trim(a.a_reflev) = d.product_id 

Waarom doe je een join op een ID met een waarde die je moet TRIMMEN? Dat lijkt me verdacht.

Verder is het natuurlijk ook een kwestie van de juiste indexen toevoegen, want die zie ik nu niet terug komen op de velden waarvoor dat logisch zou zijn.
Zoals vermeld staat in mijn startpost, deze waarde moet een TRIM over omdat de data die aangeleverd wordt spaties bevat (deze data is buiten ons beheer om). Voor welke velden zou het volgens jou logisch zijn om indexen op toe te voegen? a_reflev en product_id bevatten beiden namelijk een index op dit moment. Op a_artstat zit verder geen index, maar wanneer ik deze ORDER weg laat geeft dit verder geen performance verschil.
TheNephilim schreef op vrijdag 29 juni 2012 @ 10:18:
[...]


`a_reflev` varchar(50) NOT NULL DEFAULT '',

Volgens mij moet je die even typecasten naar INT in je JOIN. Misschien gaat het dan goed?
Typecasten gaat moeilijk, deze waarde bestaat namelijk niet alleen uit een INT.
CodeCaster schreef op vrijdag 29 juni 2012 @ 10:19:
[...]

Ik ken geen bug die specifiek vandaag getriggerd wordt in MySQL, dus wellicht is er aan de situatie iets veranderd? Heb je ineens veel meer data, is er veel meer verkeer over het netwerk?

Verder is je datamodel verre van optimaal, maar daar zul je op dit moment weinig aan kunnen doen. Lees eens iets over normalisatie. :)
Klopt, het probleem is dat de "artikels" tabel buiten ons beheer valt. Deze tabel wordt zo gevuld door voorraad/kassasysteem.
Devil schreef op vrijdag 29 juni 2012 @ 10:21:
Kun je geen trigger maken die a.a_reflev automatisch trimmed op insert?
Verder een beetje experimenteren met het maken van indexes. Hou er rekening mee dat er voor elke component die je bij de 'explain' ziet maar 1 index gebruikt kan worden. Vooral op tabel a kun je waarschijnlijk flink wat performance winst halen met bijvoorbeel een key op revlev en artstat.

Ik zou daar een beetje mee experimenteren.
Op reflev zit al een index en als ik a_artstat weg laat maakt dit verder geen performance verschil helaas.

Acties:
  • 0 Henk 'm!

  • _JGC_
  • Registratie: Juli 2000
  • Nu online
Ik zie 3 mogelijke performanceproblemen:
- TRIM in je JOIN, maar volgens jou maakt dit niks uit
- Je joint InnoDB aan MyISAM. Grote kans dat als je je MyISAM tabel ook InnoDB maakt dat je, mits je server getuned is voor InnoDB, een stuk minder performanceproblemen hebt
- Je charset voor de ene tabel is UTF8, voor de andere Latin1. Dit zorgt voor extra onnodige conversies. Maak die twee gelijk, iig op het veld dat je gaat joinen

Ik gok dat als je dat 3e punt oplost, dat je ook meteen een groot verschil gaat merken tussen wel of geen TRIM gebruiken. Vanwege de charset verschillen kan MySQL nml geen index gebruiken.

Acties:
  • 0 Henk 'm!

  • Fiander
  • Registratie: Februari 2001
  • Laatst online: 28-05 12:35
is een van onderstaande queries traag ?
SQL:
1
2
3
4
5
SELECT d.*
FROM   icecat_data d
WHERE  d.data IS NOT NULL
       AND d.invalid = 0
       AND d.pending = 1


SQL:
1
2
3
4
SELECT 
       a.*
FROM  artikeldata.artik
ORDER  BY a.a_artstat DESC


je geeft zelf aan dat de tabel eerst vooraf trimmen, en de querie daarna zonder trim uit te voeren geen verschil maakt.

en hoe vaak wijzigt de a tabel? en hoe up to date heb je die nodig? misschien deze tabel lokaal in je andere database copieren mbv een cron job, en tijdens dat copieren de join kolom alvast te casten naar een int, en een index over die kolom te plaatsen.
zolang je een functie over een kolom gebruikt, zijn indexen bijna nutteloos.

[ Voor 5% gewijzigd door Fiander op 29-06-2012 10:34 . Reden: toevoeging ]

Deze sig is een manueel virus!! Als je dit leest heb je het. Mail dit bericht naar iedereen die je kent, en verwijder alle bestanden van je computer.


Acties:
  • 0 Henk 'm!

  • PaulEm
  • Registratie: Januari 2008
  • Laatst online: 03-02 07:52
Fiander schreef op vrijdag 29 juni 2012 @ 10:31:
is een van onderstaande queries traag ?
SQL:
1
2
3
4
5
SELECT d.*
FROM   icecat_data d
WHERE  d.data IS NOT NULL
       AND d.invalid = 0
       AND d.pending = 1
code:
1
Toon Records 0 - 29 (1,237 totaal, Query duurde 0.0031 sec)
Fiander schreef op vrijdag 29 juni 2012 @ 10:31:
SQL:
1
2
3
4
SELECT 
       a.*
FROM  artikeldata.artikels a
ORDER  BY a.a_artstat DESC
code:
1
Toon Records 0 - 29 (~17,4411 totaal, Query duurde 0.1730 sec) [a_artstat: P - P]
_JGC_ schreef op vrijdag 29 juni 2012 @ 10:30:
Ik zie 3 mogelijke performanceproblemen:
- TRIM in je JOIN, maar volgens jou maakt dit niks uit
- Je joint InnoDB aan MyISAM. Grote kans dat als je je MyISAM tabel ook InnoDB maakt dat je, mits je server getuned is voor InnoDB, een stuk minder performanceproblemen hebt
- Je charset voor de ene tabel is UTF8, voor de andere Latin1. Dit zorgt voor extra onnodige conversies. Maak die twee gelijk, iig op het veld dat je gaat joinen

Ik gok dat als je dat 3e punt oplost, dat je ook meteen een groot verschil gaat merken tussen wel of geen TRIM gebruiken. Vanwege de charset verschillen kan MySQL nml geen index gebruiken.
Bedankt, hier ga ik zeker even naar kijken.

Edit: Dit was inderdaad de boosdoener, met een TRIM is het nog steeds sloom, zonder TRIM is de query gewoon weer lekker snel. Bedankt ;)

[ Voor 44% gewijzigd door PaulEm op 29-06-2012 10:55 ]


Acties:
  • 0 Henk 'm!

  • cariolive23
  • Registratie: Januari 2007
  • Laatst online: 18-10-2024
Heb je al eens met EXPLAIN gekeken hoe de database de query uitvoert? En welke index er wordt gebruikt? Zonder EXPLAIN is het erg lastig om een query te optimaliseren.

Acties:
  • 0 Henk 'm!

  • WouZz
  • Registratie: Mei 2000
  • Niet online

WouZz

Elvis is alive!

Ennuh... what about.. eerst een UPDATE draaien om a.a_reflev te trimmen? Of heb je daar geen rechten voor?

On track

Pagina: 1