[PHP/MYSQL] Dynamische view (traag bij veel records)

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
Beste Medetweakers,

Ik ben nu al een tijdje bezig met een dynamische view in PHP.
Nu heb ik er al wel een draaien maar dit wordt traag zodra er wat meer records in de DB komen.

Om een kleine testcase op te zetten heb ik 3 tabellen aangemaakt n.l.
partner_group
partner
partner_address

code:
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
CREATE TABLE `partner_group` (
`partnergroupID` VARCHAR( 32 ) NOT NULL ,
`partnergroup` VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `partnergroupID` ) 
);

CREATE TABLE `partner` (
`partnerID` VARCHAR( 32 ) NOT NULL ,
`partner_nr` VARCHAR( 50 ) NOT NULL ,
`partnertype` ENUM( 'ORG', 'PER' ) NOT NULL DEFAULT 'ORG',
`partnergroupID` VARCHAR( 32 ) NOT NULL ,
`partner_name` VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `partnerID` ) ,
INDEX ( `partnergroupID` )
);

CREATE TABLE `partner_address` (
`addressID` VARCHAR( 32 ) NOT NULL ,
`partnerID` VARCHAR( 32 ) NOT NULL ,
`address` VARCHAR( 255 ) NOT NULL ,
`zipcode` CHAR( 6 ) NOT NULL ,
`city` VARCHAR( 255 ) NOT NULL ,
PRIMARY KEY ( `addressID` ) ,
INDEX ( `partnerID` ) 
);


Vervolgens heb ik er met dit scrippie +/- 25.000 records aangemaakt

PHP:
1
2
3
4
5
6
7
8
9
10
//Insert 25.000 records
$partner_nr = -;
for($i=0; $i<25000; $i++)
{
    $partnerID = md5(microtime().microtime());
    $addressID = md5(microtime().microtime());
    $partner_nr++;
    mysql_query("INSERT INTO partner (partnerID,partner_nr,partnergroupID,partner_name) VALUES('".$partnerID."','".$partner_nr."','1','Test Company ".$i."') ");
    mysql_query("INSERT INTO partner_address (addressID,partnerID,address,zipcode,city) VALUES ('".$addressID."','".$partnerID."','parklaan 32','5623KJ','Eindhoven') ");
} //End for($i=0; $i<10000; $i++)


En dan nu mijn echte vraag.
Ik wil vanuit een SQL query dynamisch een view opbouwen, met een pagina limiet van 30 records (instelbaar)
Als je dit bekijkt in stappen lijkt het me ook niet zo moeilijk n.l:
Vervang in query alles tussen SELECT en FROM met COUNT(*)
Tel aantal records van query zonder limit
Voeg limit statement toe aan query
Voer query uit en print records...hmm ok

In het bovenstaande verhaal wordt dus een query 2x uitgevoerd... niet heel wenselijk maar in mysql 3.x heb je niet veel andere mogelijkheden denk ik.<br />

Vanaf 4.1 wordt het dacht ik beter...namelijk je krijgt de SQL statement "SQL_CALC_FOUND_ROWS"
Nu heb ik hiermee getest en tot mijn grote verbazing lijkt het alsof 2 queries alsnog sneller is...

Ik heb 2 voorbeeld script bijgedaan dus bij de ene 2 queries waarvan 1 een count..en in het tweede script de SQL functie CALC_FOUND_ROWS

Please help...ben ik nu op de goede weg of moet ik het helemaal anders aanpakken

MET SQL COUNT(*)
PHP:
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
97
98
99
100
101
102
103
104
105
106
107
108
109
110
//connect
mysql_connect("localhost","root","******");
mysql_select_db("test");

//Get Microtime
function getmicrotime()
{ 
            
    //list usec
    list($usec, $sec) = explode(" ",microtime()); 
    
    //return
    return ((float)$usec + (float)$sec); 
} //End function getmicrotime()


$BenchStart = getmicrotime();

$sql = 
"
    SELECT a.partnerID, b.partnergroup, c.address,  c.zipcode, c.city
    FROM partner as a
    LEFT OUTER JOIN partner_group as b ON a.partnergroupID = b.partnergroupID
    LEFT OUTER JOIN partner_address as c ON a.partnerID = c.partnerID
";

$sql_count = 
"
    SELECT COUNT(a.partnerID) as RowCount
    FROM partner as a
    LEFT OUTER JOIN partner_group as b ON a.partnergroupID = b.partnergroupID
    LEFT OUTER JOIN partner_address as c ON a.partnerID = c.partnerID
";


//var
$RowMax = 30;
$RowLimit = 0;
$RowCount = 0;

//Map external values
if( isset($_GET['RowLimit']) && is_numeric($_GET['RowLimit']) )
{
    $RowLimit = $_GET['RowLimit'];
} //End if( isset($_GET['RowLimit']) && is_numeric($_GET['RowLimit']) )

//Calculate rows without max
$CountData = mysql_fetch_object(mysql_query($sql_count));

//Test CountData
if(!empty($CountData->RowCount))
{
    //map ViewCount
    $RowCount = $CountData->RowCount;
} //End if(!empty($CountData->rows))

//Calculate pages
$Pages = ceil($RowCount/$RowMax);

//Build Limited Query
$sql_limited = $sql." LIMIT ".$RowLimit.",".$RowMax;

//Exec Limited Query
$result = mysql_query($sql_limited);

//Get ColumnsCount
$ColumnCount = mysql_num_fields($result);

//Print SelectBox For Pages
echo "<select onchange=\"window.location='".$_SERVER['PHP_SELF']."?RowLimit='+this.value;\">\n";
    for($i=0; $i<$Pages; $i++)
    {
        $selected = "";
        if(($i*$RowMax)==$RowLimit) { $selected = " selected "; } 
        echo "<option value=\"".($i*$RowMax)."\" ".$selected.">".($i+1)."</option>\n";
    } //End for($i=0; $i<$pages; $i++)
echo "</select>\n";

//Start Table
echo "<table border=\"1\">\n";

    //Column headers
    echo "<tr>\n";
    for($i=0; $i<$ColumnCount; $i++)
    {
        echo "<th>".mysql_field_name($result,$i)."</th>\n";
    } //End for($i=0; $i<$ColumnCount; $i++)
    echo "</tr>\n";

    //loop records
    while($data = mysql_fetch_object($result))
    {
        echo "<tr>\n";
            //Loop cols
            foreach($data as $col)
            {
                echo "<td>\n";
                    echo $col;
                echo "</td>\n";
            } //End foreach($data as $col)
        echo "</tr>\n";
    } //End while($data = mysql_fetch_object($result))

//End table
echo "</table>\n";

$BenchEnd = getmicrotime();
$BenchTime = round($BenchEnd-$BenchStart,5);

echo $BenchTime;


MET SQL_CALC_FOUND_ROWS
PHP:
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
97
98
99
100
//connect
mysql_connect("localhost","root","******");
mysql_select_db("test");

//Get Microtime
function getmicrotime()
{ 
            
    //list usec
    list($usec, $sec) = explode(" ",microtime()); 
    
    //return
    return ((float)$usec + (float)$sec); 
} //End function getmicrotime()

$BenchStart = getmicrotime();

$sql = 
"
    SELECT SQL_CALC_FOUND_ROWS a.partnerID, b.partnergroup, c.address,  c.zipcode, c.city
    FROM partner as a
    LEFT OUTER JOIN partner_group as b ON a.partnergroupID = b.partnergroupID
    LEFT OUTER JOIN partner_address as c ON a.partnerID = c.partnerID
";

//var
$RowMax = 30;
$RowLimit = 0;
$RowCount = 0;

//Map external values
if( isset($_GET['RowLimit']) && is_numeric($_GET['RowLimit']) )
{
    $RowLimit = $_GET['RowLimit'];
} //End if( isset($_GET['RowLimit']) && is_numeric($_GET['RowLimit']) )

//Build Limited Query
$sql_limited = $sql." LIMIT ".$RowLimit.",".$RowMax;

//Exec Limited Query
$result = mysql_query($sql_limited);

//Calculate rows without max
$CountData = mysql_fetch_object(mysql_query("SELECT FOUND_ROWS() as RowCount"));

//Test CountData
if(!empty($CountData->RowCount))
{
    //map ViewCount
    $RowCount = $CountData->RowCount;
} //End if(!empty($CountData->rows))

//Calculate pages
$Pages = ceil($RowCount/$RowMax);

//Get ColumnsCount
$ColumnCount = mysql_num_fields($result);

//Print SelectBox For Pages
echo "<select onchange=\"window.location='".$_SERVER['PHP_SELF']."?RowLimit='+this.value;\">\n";
    for($i=0; $i<$Pages; $i++)
    {
        $selected = "";
        if(($i*$RowMax)==$RowLimit) { $selected = " selected "; } 
        echo "<option value=\"".($i*$RowMax)."\" ".$selected.">".($i+1)."</option>\n";
    } //End for($i=0; $i<$pages; $i++)
echo "</select>\n";

//Start Table
echo "<table border=\"1\">\n";

    //Column headers
    echo "<tr>\n";
    for($i=0; $i<$ColumnCount; $i++)
    {
        echo "<th>".mysql_field_name($result,$i)."</th>\n";
    } //End for($i=0; $i<$ColumnCount; $i++)
    echo "</tr>\n";

    //loop records
    while($data = mysql_fetch_object($result))
    {
        echo "<tr>\n";
            //Loop cols
            foreach($data as $col)
            {
                echo "<td>\n";
                    echo $col;
                echo "</td>\n";
            } //End foreach($data as $col)
        echo "</tr>\n";
    } //End while($data = mysql_fetch_object($result))

//End table
echo "</table>\n";

$BenchEnd = getmicrotime();
$BenchTime = round($BenchEnd-$BenchStart,5);

echo $BenchTime;

[ Voor 0% gewijzigd door vorlox op 05-08-2006 23:16 . Reden: Typos ]


Acties:
  • 0 Henk 'm!

Verwijderd

Je primary keys zijn steeds varchar(32). Indexeren op velden met een variabele lengte is altijd veel langzamer dan op fixed length velden, zoals integers of char(32). Dit ga je ontzettend merken in je joins.

Acties:
  • 0 Henk 'm!

  • DexterDee
  • Registratie: November 2004
  • Laatst online: 13:59

DexterDee

I doubt, therefore I might be

Pak die query en zet het het woordje EXPLAIN ervoor. Voer die query eens uit in phpMyAdmin of een ander querybrowser en kijk naar de resultaten. Het geeft je waardevolle informatie over de keys die gebruikt zijn en welke indexen er gebruikt zijn om de boel aan elkaar te knopen.

Overigens als tip: MySQL kan maar op 1 index tegelijk werken in een individuele table. Dat kan ook een index zijn van meerdere velden. Heb je twee indexen in dezelfde table, dan zal de tweede niet gebruikt worden indien aangeroepen in de query. Een veel voorkomend probleem als je gaat joinen en ook nog eens gaat sorteren. In zulke gevallen is het meestal beter om subqueries te gebruiken om de dataset te beperken dan joins.

En Afterlife heeft gelijk wat betreft varchar keys. In verreweg de meeste gevallen zijn primary keys op basis van int(11) unsigned auto_increment je beste keus.

Klik hier om mij een DM te sturen • 3245 WP op ZW


Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
Beste AfterLife & DexterDee

alvast bedankt voor jullie reacties

Ik wist niet dat een varchar 32 trager was dan een char 32...goed om even naar te kijken
Het feit dat ik geen autoincremental key gebruik heeft te maken met de mogelijkheid tot replicatie...
ik gebruik hier MySQL en geen SQL server.
Ook wil ik graag de compatibiliteit met MySQl 3.x in de gaten houden.....aardig wat plesk installaties waar 3.x wordt gebruikt..

Verder begrijp ik dat je met indexen een eind kan komen...ook gaat het me verder niet over de structuur van de tabellen want ook met een autoincrement blijf ik het zelfde probleem houden...vanaf zo'n 25.000 + records wordt het allemaal een stuk trager.

Mijn vraag is eigenlijk dus...de manier waarop ik de view (PHP) in elkaar zet. is dat een goede manier of heeft iemand een beter idee??

En een dubbele outer join...moet niet echt een probleem zijn lijkt me.. Hoe moet je andere je data bij elkaar halen.....
Tja ik kan nog gaan on -normaliseren maar dat gaat tegen mijn gedachten in..

Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
25.000 records is niets voor MySQL. Maar zorg wel voor een goede data-structuur, want hoewel een auto_increment niet helpt voor de snelheid, doet een integer-veld dat wel. Joinen op een tekst-veld is over het algemeen een no-go. Verder weet je door het invoegen van een md5 nooit zeker of je wel een unieke waarde krijgt. Als basisregel kun je aanhouden dat je op een uniek-id veld een auto_increment wilt. Zo'n eenvoudige query zou met 25.000 velden zo uitgevoerd moeten zijn.
Tot zover over je database-structuur, nu over je script. De naam van $rowLimit suggereert dat je niet meer dan $rowLimit rijen terugkrijgt. Een logische naam zou $rowStart zijn. Voor $rowCount zou $rowLimit dan wel weer een logische naam zijn, want op de laatste pagina krijg je niet altijd zoveel resultaten als $rowCount zou suggereren.

Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
GlowMouse
Bedankt voor je reactie, maar hier heb ik echt niks aan.
Bovenstaande scripts zijn inelkaar gezette voorbeelden ter illustratie...ga dan niet zeuren over een variabele naam als daar niet het probleem zit...zucht het gaat om 2 queries in MySQl 3 of in met SQL_CALC_FOUND_ROWS in MySQl 4.X en hoger
En hoe los jij met een autoincremental veld dan een replicatie 2way op met MySql 3.X
en hoe regel je dan het vooraf aanmaken van een structuur / dataset over meerdere tabellen met meerdere records.
Dus 1 partner met 3 adressen?
Dan zul je dus moeten weten welk ID's er in alle tabellen komen??
Bij een incremental zul moet je altijd eerst 1 record inserten en dan mysql_insert_id() doen alvorens je de andere tabellen kunt vullen.......niet fijn. Dan moet je bijvoorbeeld eerst de partner opslaan voordat je er adressen aan kunt hangen.
En waarom mag ik niet joinen op een varchar veld...dat snap ik niet helemaal...dat je snelheid inboekt snap ik maar verder...who cares?

met andere woorden mwa

Ter informatie
Ik heb in SAP gekeken hoe dit werkt..althans getracht
In SAP CRM moet je iets van nummerreeksen opgeven zoiets als 200000 - 400000 is voor systeem 1 en 500000 - 600000 is voor systeem 2...zucht
Het is iets om even naar te kijken.
Verder zie ik in SAP R3 mara helemaal geen ID ???
Het id is daar de mandant / artikelnummer ??? aah en dat is ook een char

Zucht en nog iets??
een char is max 30..AARGHH


WAT NU.
ik kan natuurlijk wel weer terug gaan naar incremetalID's maar dan heb ik dus in elke tabel weer een extra veld nodig met alsnog een varchar(32)....en wat doe ik dan bij inserten...dus als ik op server in in tabel partner een record heb met ID 1 en op de andere server ook... en er zijn al adressen aangemaakt met dat ID
dan zul je in je replication script dus zwaar moeten gaan rekenen zo van ok dus dat is ID 1 en dan wil ik ook alle adres records met partnerID 1 maar dan insert ik hem op de andere server en krijgt hij ID 2 en dan loop ik langs alle subrecords en maak ik van 1 2 ......hmm is dat echt hoe het zou moeten dan..

ben ik de enige met dit probleem.

[ Voor 49% gewijzigd door vorlox op 06-08-2006 23:27 . Reden: Ter informatie toegevoegd ]


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
vorlox schreef op zondag 06 augustus 2006 @ 23:01:
GlowMouse
Bedankt voor je reactie, maar hier heb ik echt niks aan.
Bovenstaande scripts zijn inelkaar gezette voorbeelden ter illustratie...ga dan niet zeuren over een variabele naam als daar niet het probleem zit...zucht
:|
het gaat om 2 queries in MySQl 3 of in met SQL_CALC_FOUND_ROWS in MySQl 4.X en hoger
Welke sneller is ben je denk ik snel genoeg achter. Maar om het geheel te optimaliseren zul je bij de database moeten zijn. De queries worden blijkbaar niet zo snel uitgevoerd.
En hoe los jij met een autoincremental veld dan een replicatie 2way op met MySql 3.X
Zou goed moeten gaan
en hoe regel je dan het vooraf aanmaken van een structuur / dataset over meerdere tabellen met meerdere records.
Dus 1 partner met 3 adressen?
Dan zul je dus moeten weten welk ID's er in alle tabellen komen??
Bij een incremental zul moet je altijd eerst 1 record inserten en dan mysql_insert_id() doen alvorens je de andere tabellen kunt vullen.......niet fijn. Dan moet je bijvoorbeeld eerst de partner opslaan voordat je er adressen aan kunt hangen.
Als dat een van de eisen is, zit je database verkeerd in elkaar.
En waarom mag ik niet joinen op een varchar veld...dat snap ik niet helemaal...dat je snelheid inboekt snap ik maar verder...who cares?
Snelheid was toch juist het probleem? Volgens mij ben jij dan degene die dat niet leuk vindt.

Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
Ik geloof niet dat je me wilt begrijpen, en je wilt ook niet lezen.
mysql 3.x ...2 way
Als dat een van de eisen is, zit je database verkeerd in elkaar.
Hahahah ik ben blij dat je dit zegt want dan hoef ik dus niet verder met je te praten.
Geef nu eens aan dan hoe jij die bovenste 3 tabellen anders zou maken..
Snelheid was toch juist het probleem? Volgens mij ben jij dan degene die dat niet leuk vindt.
Ja ik ben een miereneuker ja er zit verschil in 0.01 en 0.001 ja
en dat heeft dus geen drol met INT of VARCHAR te maken (net geprobeerd) maar in het feit dat je 2 keer een query doet....

En als je alles zo goed weet geef dan eens een voorbeeld van hoe jij het zou doen en laat anders de ruimte vrij voor mensen die hulp verschaffen in plaats van jouw gemekker en vaardigheid in quoten


CRISP HELLUP |:(

Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Zullen we gewoon vriendelijk blijven? :)

Joinen op een varchar veld is raar omdat je normaal joint op keys, en natural keys zoals strings die door de gebruiker gewijzigd kunnen worden zijn daar niet geschikt voor. Verander je de key in de hoofdtabel, dan moet je ook alle tabellen aanpassen die die waarde als foreign key gebruiken. Neem dus gewoon een extra veld op voor het id, dat niet meer is dan een unieke interne identificatie.

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
Zucht sorry, ben irritated omdat niemand echt ff leest.
Ik snap dat je normaal een INT auto enz neemt voor een key ..en dat je normaal gesproken user input niet moet vertrouwen omdat je zoals je al zegt dan doorreken acties ala LOTUS NOTUS krijgt.
Echter ik gebruik dit veld als een type GUID zoals in SAP CRM of een unique in SQL server , het geval is dus een unieke sleutel voor elk record...deze wordt door het formulier gegenereerd zegmaar.. nu werkt dit verder precies hetzelfde als een autonummertje. echter het geeft dus zeker wat loss qwa performance echter dit is niet de loss die ik met dit topic bedoelde..
Ook heb ik net wat zitten testen en het verschil valt echt wel mee. Echter zodra het op joins aankomt merk je inderdaad meer verschil.
Nu heb ik alleen die GUID nodig vanwege een replicatie naar een andere server. iets wat opzich ook gewoon draait hoor met tabellen over 66.000 records.

Dus nogmaals de uitleg in het kort
Ik heb 2 typen PHP views gemaakt...zoals in start post beschreven.
Om er een door pagina's gescheiden layout aan te geven, doe ik 2 queries.
Ongeacht of het nou varchar(32) guids of autonummertjes zijn, de output naar de user wordt trager naarmate er meer records +/- 25.000 in de tabellen komen.

Ja duh zul je zeggen...ja ook dat snap ik...maar op wat voor manier zet je dan een PHP view op zodat de wachttijd consistent is..

en een sleep(60) is niet grappig ;)

Acties:
  • 0 Henk 'm!

  • XWB
  • Registratie: Januari 2002
  • Niet online

XWB

Devver
DexterDee schreef op zondag 06 augustus 2006 @ 13:23:
Overigens als tip: MySQL kan maar op 1 index tegelijk werken in een individuele table. Dat kan ook een index zijn van meerdere velden. Heb je twee indexen in dezelfde table, dan zal de tweede niet gebruikt worden indien aangeroepen in de query. Een veel voorkomend probleem als je gaat joinen en ook nog eens gaat sorteren. In zulke gevallen is het meestal beter om subqueries te gebruiken om de dataset te beperken dan joins.
Ook met de innodb engine?

March of the Eagles


Acties:
  • 0 Henk 'm!

  • DexterDee
  • Registratie: November 2004
  • Laatst online: 13:59

DexterDee

I doubt, therefore I might be

Hacku schreef op maandag 07 augustus 2006 @ 17:00:
[...]

Ook met de innodb engine?
Ja, ook met de innoDB engine helaas :|

@vorlox:
Je hoeft mij niets te vertellen over Lotus Notes, ik ben CLP 4,5 en 6 principal ;)
In onze corporate omgeving doen wij ook veel PHP development (naast domino) en hoe wij het hebben opgelost is met een generieke view template die gebaseerd is op een iframe. Het content gedeelte van de view wordt dus met een aparte URL geladen, zodat de gebruiker alvast de schil van de applicatie ziet. Totdat de view zelf is opgebouwd, zetten we er een stukje HTML voor in de plaats met een indefinite progressbar, zodat de gebruiker weet dat er iets gaande is. Een voorbeeld van zo'n progressbar kun je hier vinden:
http://webfx.eae.net/dhtml/xblmarquee/progressbar.html

Zodra de contents van de view terug komt van de server, toont het iframe de juiste gegevens. Op deze manier krijgt de gebruiker visuele feedback dat er wat gebeurt in de backend, of het nu 1 seconde of 50 seconden duurt. Hetzelfde mechanisme herhalen we ook voor grote exports of andere tijdrovende bewerkingen op de MySQL database.

Klik hier om mij een DM te sturen • 3245 WP op ZW


Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
He DexterDee...
Je zou wel eens een punt kunnen hebben..
Ik ga even wat experimenteren met een iframpje

thanks for the supprt

Acties:
  • 0 Henk 'm!

  • Grum
  • Registratie: Juni 2001
  • Niet online
Kan je misschien wat uitleggen?

Je gebruikt als argument dat je Master-Master replicatie script(!) niet werkt onder MySQL3 als je ints zou gebruiken. Kan je me uitleggen hoe je ooit gedacht het werkende te maken onder MySQL4? Zonder transacties?

Je kan nog steeds aan beide kanten tegelijk data inschieten met dezelfde primary key en hoe je het ook zal wenden of keren je blijft altijd race condities hebben.

Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
Heel simpel

Als je op 1 van de 2 servers een script aanspreekt genereert hij zelf een GUID..
deze wordt dan op bijde servers ingespoeld...met ID's is dat een hoop gezeur en met GUID's nooit.
Want als de connectie tussen de servers down is kun je namelijk op beide servers gewoon doorwerken....en nadat ze weer connecten....spoelen ze de data cross gewijs over....met een autonummer krijg ik dit gewoon niet fatsoenlijk werkend...onder 3 he...mensen...

Echter ik vrees dat we niet ver komen met deze discussie....want de meeste hier komen niet verder dan autoincremental ID's....zoals MS access dat doet, en ik ben meer aan het kijken hoe echte oplossingen zoals SAP / oracle enz het doen....

Echter zij hebben het voordeel van oracle en een perfecte middleware van SAP..
Zelf denk ik dus dat ik misschien een stap terug moet....en een middleware moet gaan bouwen...want ik wordt zelf ook niet blij van deze oplossing maar goed tis niet anders...

budget is budget

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 02:21

Janoz

Moderator Devschuur®

!litemod

Ik vermoed dat de rest niet de enige is die niet goed leest. Een integer is niet hetzelfde als een autoincremental id.

Toch grappig om te zien dat je hoog van de toren blaast over professionele oplossingen als in SAP en Oracle en de rest hier afdoet als 'access ontwikkelaartjes', maar vervolgens wel de beginnersfout maakt om een getal te nemen, deze hexadecimaal gepresenteerd in een string te stoppen en vervolgens tegen iedereen lopen zeuren dat dat blijkbaar de enige manier is om een 64-bit waarde in mysql op te slaan.

Ik raad je aan om nog eens eventjes tussen de verschillende datatype te kijken in de MySQL handleiding. Een join op een bigInt is nog altijd een stuk sneller dan een varchar.

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Pssst, Janoz, een md5 geeft een 128 bits int ;)

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
Beste Janoz..... lezen.....er is niemand in heel het topic die de vraag heeft beantwoord....dus 1 of twee queries of een andere oplossing.....de hele duscussie is dus op niks gebaseerd.. want ik heb getest met een int 11 AUTO en een varchar 32 ..en wat denk je als je 2x een query uitvoert wordt het 2x zo traag ook met INT's dusssssssssss. wat zeg je nu eigenlijk dat je mijn vraag niet begrijpt?

Ben het nu wel een beetje zat hoor...hoog van de toren blazen..pfff magertjes antwoord hoor.....
het heeft verder nog niks met een bigint ofoz te maken want ik zoek eigenlijk een unique...
Maar i.p.v af gezeken te worden kwam ik hier met de vraag omdat ik hoopte dat je met gezamelijke kennis tot een mooie oplossing zou kunnen komen........maar het enige wat jullie doen is je aangevallen voelen... en verder aanvallen....waarom is me niet helemaal duidelijk maar goed.
Verder snap ik ook niet dat op een fatsoenlijk opgebouwde vraag de topic starter wordt teruggefloten

Maar goed als niemand wil helpen heeft wat mij betreft dus heel dit forum geen nut meer....want als ik afgezeken wil worden kan dat overal wel.
maar vervolgens wel de beginnersfout maakt om een getal te nemen, deze hexadecimaal gepresenteerd in een string te stoppen en vervolgens tegen iedereen lopen zeuren dat dat blijkbaar de enige manier is om een 64-bit waarde in mysql op te slaan.
Ik zeur daar niet over.....aararrgh lezen....ik praat over de opbouw van een dynamische view en dat HEEFT niks te maken of je joint op een int of char.
Het GAAT OM het feit dat je moet weten hoeveel records je totale quey heeft zodat je het per pagina kan scheiden.......ZUCHT
Hoe zou jij het dan doen..dus ik wil een UNIQUE / GUID....en geen autoincremetal.

-dus hoe maak jij je GUID
-En in welk type veld zet jij dit dan neer.

Ter info
Volgende class kwam ik tegen om een andere guid te bouwen..
Echter ook dan zal ik een varchar moeten gebruiken om op te slaan..??
more ideas??

code:
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
class System 
{ 
    function currentTimeMillis() 
    { 
        list($usec, $sec) = explode(" ",microtime()); 
        return $sec.substr($usec, 2, 3); 
    } 

} 

class NetAddress 
{ 

    var $Name = 'localhost'; 
    var $IP = '127.0.0.1'; 
     
    function getLocalHost() // static 
    { 
        $address = new NetAddress(); 
        $address->Name = $_ENV["COMPUTERNAME"]; 
        $address->IP = $_SERVER["SERVER_ADDR"]; 

        return $address; 
    } 

    function toString() 
    { 
        return strtolower($this->Name.'/'.$this->IP); 
    } 

} 

class Random 
{ 
    function nextLong() 
    { 
        $tmp = rand(0,1)?'-':''; 
        return $tmp.rand(1000, 9999).rand(1000, 9999).rand(1000, 9999).rand(100, 999).rand(100, 999); 
    } 
} 

// Èý¶Î 
// Ò»¶ÎÊÇ΢Ãë Ò»¶ÎÊǵØÖ· Ò»¶ÎÊÇËæ»úÊý 
class Guid 
{ 

    var $valueBeforeMD5; 
    var $valueAfterMD5; 

    function Guid() 
    { 
        $this->getGuid(); 
    } 
// 
    function getGuid() 
    { 
        $address = NetAddress::getLocalHost(); 
        $this->valueBeforeMD5 = $address->toString().':'.System::currentTimeMillis().':'.Random::nextLong(); 
        $this->valueAfterMD5 = md5($this->valueBeforeMD5); 
    } 

    function newGuid() 
    { 
        $Guid = new Guid(); 
        return $Guid; 
    } 

    function toString() 
    { 
        $raw = strtoupper($this->valueAfterMD5); 
        return substr($raw,0,8).'-'.substr($raw,8,4).'-'.substr($raw,12,4).'-'.substr($raw,16,4).'-'.substr($raw,20); 
    } 

}


en een stukje op PHP.net
code:
1
2
3
4
5
// no prefix
$token = md5(uniqid());

// better, difficult to guess
$better_token = md5(uniqid(rand(), true));

[ Voor 72% gewijzigd door vorlox op 08-08-2006 13:11 ]


Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
.oisyn schreef op dinsdag 08 augustus 2006 @ 12:03:
Pssst, Janoz, een md5 geeft een 128 bits int ;)
hmm php zegt wat anders een 128 bits hex...sorry

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

Je hebt ook echt compleet geen idee waar je het over hebt he :D

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
schijnbaar niet en jullie ook niet want niemand geeft fatsoenlijk antwoord en komt met een valide oplossing

Acties:
  • 0 Henk 'm!

  • WormLord
  • Registratie: September 2003
  • Laatst online: 10:10

WormLord

Devver

Ik zou de count gewoon met COUNT(*) ophalen en er op vertrouwen dat MySQL het query plan van de eerste lang genoeg cachd om bij de 2de nog een keer te gebruiken.

SQL_CALC_FOUND_ROWS ken ik nog niet, en kon net ook geen informatie vinden daarover op de mysql site. Dus over die optie kan ik weinig zinnigs zeggen.

Maar eerlijk gezegd, als je eigen testen aantonen dat SQL_CALC_FOUND_ROWS trager, dan zou ik het gewoon niet op die manier doen. :)

Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 03:42

.oisyn

Moderator Devschuur®

Demotivational Speaker

vorlox schreef op dinsdag 08 augustus 2006 @ 14:17:
schijnbaar niet en jullie ook niet want niemand geeft fatsoenlijk antwoord en komt met een valide oplossing
Ok, speciaal voor jou.

Een "integer" is gewoon een getal in Z, oftewel een positief danwel negatief geheel getal. Het MD5 algoritme berekent een 128 bits hash van een stukje data, die je op kunt slaan in een 128 bits int. PHP kent geen 128 bits ints en die geeft dus de representatie van die data als een hexadecimale string. Dat het gerepresenteert wordt als een string met een andere basis dan jij gewend bent (namelijk basis 16 ipv 10, daar staat de 'hex' dus voor) wil nog niet zeggen dat het ineens geen getal meer is.

Wat de mensen jou in deze draad duidelijk proberen te maken is dat het vergelijken op een string langzaam is en dus kun je het beter als getal behandelen. Maar ook dat het gebruik van die md5 als primary key in eerste instantie al een slecht idee is (het is niet gegarandeerd dat elk id verschillend is).

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


Acties:
  • 0 Henk 'm!

  • amoen
  • Registratie: Juni 2003
  • Laatst online: 30-06 22:13
@vorlox

in mijn geval heb je gelijk, ik lees niet elke letter van dit topic.
ik lees altijd eerst globaal, en besluit dan wel/niet of ik ergens bij kan helpen.

gelukkig vielen mij meteen jouw ongeduld en lage irritatiegrens op.
en het bijna kinderachtige gekreun en gesteun tussen je tekst.

een beetje meer respect voor de 'hulp' (al dan niet nuttig) mag best lijkt me.
misschien dat anderen dan wat makkelijker te overtuigen zijn
om dieper te graven naar de oplossing voor je probleem

want zo bereik je helemaal niks...
succes

heeeeee ..... hoe is het?


Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
Bedankt, wormlord je bent de eerste die de vraag heeft gelezen.
Ik moet zeggen ik kende SQL_CALC_FOUND_ROWS ook niet.... na een aantal meer test ben ik erachter gekomen dat een LIMIT 10,10 sneller is dan 11100,10 en bij SQL_CALC_FOUND_ROWS is het altijd even traag....bij hele grote tabellen kan dit dus weer wel voordelig zijn.

Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
amoen het spijt me, heb op moment inderdaad lage irritatie grens...maar ben er al lang mee bezig en ik lijk nergens te komen.. je moet ervanuit gaan dat alle hulp welkom is.

Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
oisyn bedankt....dat stukje is duidelijk. En voor de uniekheid van de md5 hebben we eventueel een oplossing. Echter blijf je dan met performace zitten.
Ik vraag me dan ook af hoe ik dit moet gaan oplossen, toch weer alles terugzetten naar INT en dan per server een reeks vastzetten??

Is er een mogeljkheid om toch die md5 terug om te zetten naar een INT en dan in een bigint op te slaan??

nee anders hoe zouden jullie het aanpakken
nummerreeksen vastelggen per server??
dus server 1 tabel 1
id 1 - 100.000
en sever 2 tabel 1
id 200.000 - 300.000

is dat dan een oplossing??
please denk nog even mee aub...

[ Voor 22% gewijzigd door vorlox op 08-08-2006 15:02 ]


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

vorlox schreef op dinsdag 08 augustus 2006 @ 14:27:
Bedankt, wormlord je bent de eerste die de vraag heeft gelezen.
Als de mensen hier je vraag niet gelezen hebben volgens jou, dan kan ik niet anders zeggen dan dat jij de antwoorden ook niet goed leest. Bekijk de laatste post van .oisyn nog eens goed, je bent echt niet handig bezig. :)
Ah, daar was je nog niet aan toegekomen. :)

[ Voor 6% gewijzigd door NMe op 08-08-2006 14:37 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • Grum
  • Registratie: Juni 2001
  • Niet online
vorlox schreef op dinsdag 08 augustus 2006 @ 11:12:
Heel simpel

Als je op 1 van de 2 servers een script aanspreekt genereert hij zelf een GUID..
deze wordt dan op bijde servers ingespoeld...met ID's is dat een hoop gezeur en met GUID's nooit.
Want als de connectie tussen de servers down is kun je namelijk op beide servers gewoon doorwerken....en nadat ze weer connecten....spoelen ze de data cross gewijs over....met een autonummer krijg ik dit gewoon niet fatsoenlijk werkend...onder 3 he...mensen...
Toch lees je nu over een stuk bij mij heen, hoe voorkom jij racecondities ?

Als je op beide servers tegelijkertijd een stuk data inschiet met een primary key die hetzelfde is maar met andere data erbij (iemand maakt een typo - whatever). Hoe wil je dat dan op gaan lossen?

Overschrijf je dan bot een record omdat ze bij het syncen al aan 2 kanten staan?
Negeer je gewoon 1 van de 2 en gooi je dus mogelijk de verkeerde weg?
Negeer je ze beide en laat je iemand handmatig kiezen welke data van de 2 records je nu wel wil ? (word leuk als je al afhankelijke data hebt)

In mijn ogen is het sowieso al raar dat je een 'eigen' replicatie 'script' gebruikt ipv de bestaande replicatie mogelijkheden in de database uitbuit.

BTW: MySQL 3.x hoef je niet perse meer te supporten vanaf het einde van dit jaar; zie hier.

Misschien is het handig om hier rekening mee te houden en ipv je vast te bijten in het moeten hebben van een oplossing, een soepel migratie-traject bedenken voor de 'slachtoffers' die 'moeten' upgraden.

Acties:
  • 0 Henk 'm!

  • vorlox
  • Registratie: Juni 2001
  • Laatst online: 02-02-2022

vorlox

I cna ytpe 300 wrods pre miute

Topicstarter
Beste Grum,
Ik vrees inderdaad dat ik MySQL 3 moet loslaten, ik heb gezein dat MySQl 5.1 veel van mijn eisen in zich heeft..ik ga hier eerst even mee testen.
Overschrijf je dan bot een record omdat ze bij het syncen al aan 2 kanten staan?
Negeer je gewoon 1 van de 2 en gooi je dus mogelijk de verkeerde weg?
Negeer je ze beide en laat je iemand handmatig kiezen welke data van de 2 records je nu wel wil ? (word leuk als je al afhankelijke data hebt)
Ja, ik heb in al mijn tabellen een last modified zitten...degene die wint wint...zeg maar dus de laatst geupdate die wordt naar de andere server gemoved.... met guid is dit juist zo makkelijk...omdat elk record dus een uniek nummer heeft. En natuurlijk kan het in theorie voorkomen dat 1 record nog net gewijzigd wordt voordat deze geupdate wordt....tja dan is het pech....maar tot nu toe heb ik hier niemand over gehoord.

Ik ben natuurlijk verder gaan zoeken en verder gaan zoeken...en ik kom er meer en meer achter dat guid helemaal niet zo slecht zijn echter in MySQL wordt dit in de inno-db engine dus gewoon verkeerd afgehandeld.

Verder kreeg ik nog een tip om eens verder te kijken dan MySQl...en kwam ik uit bij PostGreSQL
...standaard zit het er niet in maar je kunt voor PostGresql een datatype guid als plugin draaien.
Verder viel mijn mond open na een aantal benchmark tests..

Postgres is met een GUID 5 a 6 keer zo snel met 50.000 records als MySQL..dat is toch best een signifcant verschil..

Mijn conclusie tozover is dat ik toch erg graag met UUID's of GUID's blijf werken, en dat MySQlL eigenlijk dit niet tot slecht ondersteunds.. of zeg ik nu weer heel verkeerde dingen

Toch bedankt voor jullie moeite

_/-\o_

[ Voor 88% gewijzigd door vorlox op 10-08-2006 17:55 ]

Pagina: 1