Permalänk

Otroligt långsam query

Jag har en mysql query inne i en klassfunktion som är väldigt simpel:

mysql_query('UPDATE strider SET hitpoints=' . $hp . ' WHERE id=' . $this->id);

Scriptet körs på ca. 0.06-0.1 sekunder med linjen och 0.0003 utan. Vad kan problemet vara?
hitpoints och id är båda int(11)

Visa signatur

Intel 2500k @ 3,3ghz ● ASUS 6870 1GB Crossfire ● ASUS Sabertooth P67 ● XFX 750w ● 4Gb DDR3 ● Bitfenix Outlaw

Permalänk
Medlem

Din query är inte så säker och du verkar inte avsluta den på ett korrekt sätt.
Jag förstår inte varför du skriver $this>id, antar att $this är en variabel som innehåller ditt id?

Isåfall testa följande:

mysql_query("UPDATE `strider` SET `hitpoints`='$hp' WHERE `id`='$this'");

Permalänk
Skrivet av MrCaps:

Jag förstår inte varför du skriver $this>id, antar att $this är en variabel som innehåller ditt id?

Snarare så att det är en klass som innehåller en variabel vid namn id så att bara skriva $this kommer inte att fungera.

Är det bara denna fråga som tar lång tid eller är det alla frågor?

Permalänk
Medlem
Skrivet av the_weird:

Snarare så att det är en klass som innehåller en variabel vid namn id så att bara skriva $this kommer inte att fungera.

Är det bara denna fråga som tar lång tid eller är det alla frågor?

Ja så kan det vara, tänkte ej på det!
Men i sådana fall borde det räcka med att lägga till >id efter $this, så länge det inte är hela din databas som är långsam

Permalänk
Medlem

Hur många rader har strider, och är id ett index?

Permalänk
Medlem

ligger din databasfråga i en loop?
Om så är fallet så kommer ju frågan köras k gånger.
Ett bättre alternativ är att bulka ihop uppdateringarna för alla k objekt och köra en databasfråga efter loopen.

Visa signatur

weeeee

Permalänk
Medlem
Skrivet av Björnen123:

Scriptet körs på ca. 0.06-0.1 sekunder med linjen och 0.0003 utan.

Vad är "linjen"? Kommandoradsprompt i något sql-verktyg?

Att queryns totala exekveringstid är mycket snabbare direkt i ett sql-verktyg som redan har en koppling mot databasen vore inte så underligt, jämfört med att lägga på tiden det tar att ansluta mot databasen.

Bara ett skott i mörkret.

Visa signatur

5950X, 3090

Permalänk
Medlem
Skrivet av backfeed:

Vad är "linjen"? Kommandoradsprompt i något sql-verktyg?

Att queryns totala exekveringstid är mycket snabbare direkt i ett sql-verktyg som redan har en koppling mot databasen vore inte så underligt, jämfört med att lägga på tiden det tar att ansluta mot databasen.

Bara ett skott i mörkret.

Jag tror han menar att hela scriptet utan nämnd kodrad tar 0.0003s och då han kör hela scriptet med kodraden så tar det 0.06-0.1 ca 2.6x längre tid.

Visa signatur

weeeee

Permalänk
Medlem

Var ligger din databas?

Queryn ovanför kan du inte få snabbare en vad du redan skrivit den så den är inte problemet.

#1 Det tar tid att koppla upp dig till en SQL databas, vist relativt fort men det är fortfarande "Tid".
#2 Det tar tid att göra en query, ytligare ett anrop till databasen.

Vad jag försöker säga, tar det 10ms eller 50ms eller 100ms till din databas, för varje Query så tar det MINST denna tid + tiden att utföra queryn.

Sedan hur belastad är databasen, hur många rader finns det i tabellen, hur ser dina Index ut? O.s.v. Alla viktiga frågor.

Visa signatur

Speldator: i7-8700k, 32GB DDR4, RTX2080
Server 1: SB 2500k, MZI -P67GD55, 32GB DDR3, Corsair MX 240GB SSD
Surface Pro 2017, Konsoler: Typ alla, Oculus Rift

Permalänk
Skrivet av MrCaps:

Din query är inte så säker och du verkar inte avsluta den på ett korrekt sätt.
Jag förstår inte varför du skriver $this>id, antar att $this är en variabel som innehåller ditt id?

Isåfall testa följande:

mysql_query("UPDATE `strider` SET `hitpoints`='$hp' WHERE `id`='$this'");

Avsluta den på ett korrekt sätt? Hur menar du? Queryn jag skrev kommer vara bra mycket snabbare än denna då din måste kolla igenom citattecknena efter variabler.
$this refererar ju till det nuvarande Objektet och hämtar variableln id. Varför du väljer att sätta apostrofer överallt (varför sätter du tecken runt tabellerna!??!?!) förvirrar mig rejält. Både $hp och $this->id är nummer.
Förresten, hur kan frågan inte vara säker? Båda variablerna är genererade av servern och de kan bara vara (int)

Skrivet av the_weird:

Snarare så att det är en klass som innehåller en variabel vid namn id så att bara skriva $this kommer inte att fungera.

Är det bara denna fråga som tar lång tid eller är det alla frågor?

Bara denna

Skrivet av MrCaps:

Ja så kan det vara, tänkte ej på det!
Men i sådana fall borde det räcka med att lägga till >id efter $this, så länge det inte är hela din databas som är långsam

Kommer inte fungera, nej.

Skrivet av Spannen:

Hur många rader har strider, och är id ett index?

1 rad och ja.

Skrivet av mounte:

ligger din databasfråga i en loop?
Om så är fallet så kommer ju frågan köras k gånger.
Ett bättre alternativ är att bulka ihop uppdateringarna för alla k objekt och köra en databasfråga efter loopen.

Hade frågan legat i en loop hade jag nog sagt det

Skrivet av mounte:

Jag tror han menar att hela scriptet utan nämnd kodrad tar 0.0003s och då han kör hela scriptet med kodraden så tar det 0.06-0.1 ca 2.6x längre tid.

Precis.

Skrivet av MugiMugi:

Queryn ovanför kan du inte få snabbare en vad du redan skrivit den så den är inte problemet.

Precis. Det var det jag tänkte

Jag ändrade lagrigsmotor på tabellen från InnoDB till MyISAM vilket verkade fixa den långsamma laddningstiden. Någon som har tips på vilken lagringsmotor man ska använda på olika sorters tabeller?

Visa signatur

Intel 2500k @ 3,3ghz ● ASUS 6870 1GB Crossfire ● ASUS Sabertooth P67 ● XFX 750w ● 4Gb DDR3 ● Bitfenix Outlaw

Permalänk
Medlem

Hur mycket är din förväntade last på den här frågan?

Jag kan inte php, men tips för att få en databas fråga snabbare kan vara att kolla upp vilken typ av binding du använder för dina variablar.

Om du tänker dig en Oracle databas, så kan du göra en query.
Det den då måste göra är att, den måste kolla exakt hur queryn ser ut, den måste kolla ifall din användare har rättigheter att göra vad du försöker göra, i de tabellerna du försöker göra det i. Tillsammans med en massa andra saker. Detta tar onödigt mycket tid.

Det man då gör för att undvika detta är att använda något som kallas för att man binder variablerna, så man garanterar en soft parse.

Detta innebär då att du t ex säger: "select * from my_table where id=?", vilket innebär att din databas kan cacha den frågan exakt som den ser ut, då nästan du ställer exakt samma fråga så vet den, aha, det är den här frågan igen, då vet jag redan att den här användaren har access till de tabellerna den försöker att göra. Finns exempel där du från att byta mellan soft och hard parse kan få från 300-3000 tps (transactions per second).

Tänk på att nu när du byter till MyISAM, så den största skillnaden vad jag vet är att låser på tabell nivå jämfört med InnoDB som låser på rad-nivå, vilket gör att om du gör den här queryn i stor mängd så kommer den inte klara av det..

Nu som sagt vet jag inte om detta hjälper dig alls, bara små tips som KANSKE hjälper dig nu eller i framtiden eller någon annan.

Lycka till!

Permalänk
Medlem

Har du funderat på att använda t.ex. redis som lagringsmotor istället (in memory database) där du kan ha som tillägg att redis skriver till traditionell databas emellanåt.

Visa signatur

weeeee

Permalänk
Medlem
Skrivet av nesohc:

Tänk på att nu när du byter till MyISAM, så den största skillnaden vad jag vet är att låser på tabell nivå jämfört med InnoDB som låser på rad-nivå, vilket gör att om du gör den här queryn i stor mängd så kommer den inte klara av det..

Mycket sant, dock till hjälp så stödjer inte MyISAM transaktioner så själva tabell låsningarna blir inte så extremt långa men kan bli ett problem om man göra stora updates eller inserts, eller rent ut sagt updatterar mer en skriver och (Oftast mer en 90% ) i de fallen är InnoDB bättre val för de tabellerna.

---

Samt för OP.

MyISAM = Bara tabeller, den saknar relationer samt transaktioner. Lämpar sig för data som inte år så viktig att den har exakta relationer.
InnoDB = Relations databas samt Transaktions databas.

Visa signatur

Speldator: i7-8700k, 32GB DDR4, RTX2080
Server 1: SB 2500k, MZI -P67GD55, 32GB DDR3, Corsair MX 240GB SSD
Surface Pro 2017, Konsoler: Typ alla, Oculus Rift

Permalänk
Medlem
Skrivet av nesohc:

Hur mycket är din förväntade last på den här frågan?

Jag kan inte php, men tips för att få en databas fråga snabbare kan vara att kolla upp vilken typ av binding du använder för dina variablar.

Om du tänker dig en Oracle databas, så kan du göra en query.
Det den då måste göra är att, den måste kolla exakt hur queryn ser ut, den måste kolla ifall din användare har rättigheter att göra vad du försöker göra, i de tabellerna du försöker göra det i. Tillsammans med en massa andra saker. Detta tar onödigt mycket tid.

Det man då gör för att undvika detta är att använda något som kallas för att man binder variablerna, så man garanterar en soft parse.

Detta innebär då att du t ex säger: "select * from my_table where id=?", vilket innebär att din databas kan cacha den frågan exakt som den ser ut, då nästan du ställer exakt samma fråga så vet den, aha, det är den här frågan igen, då vet jag redan att den här användaren har access till de tabellerna den försöker att göra. Finns exempel där du från att byta mellan soft och hard parse kan få från 300-3000 tps (transactions per second).

Tänk på att nu när du byter till MyISAM, så den största skillnaden vad jag vet är att låser på tabell nivå jämfört med InnoDB som låser på rad-nivå, vilket gör att om du gör den här queryn i stor mängd så kommer den inte klara av det..

Nu som sagt vet jag inte om detta hjälper dig alls, bara små tips som KANSKE hjälper dig nu eller i framtiden eller någon annan.

Lycka till!

Jag vet inte om jag är ute o cyklar här men tar inte en sökning på "select * from my_table..." (alla fält) längre tid än just de specifika fält man vill åt? tex "select faltnr1 from my_table..." ??

Permalänk
Medlem
Skrivet av tekFreP:

Jag vet inte om jag är ute o cyklar här men tar inte en sökning på "select * from my_table..." (alla fält) längre tid än just de specifika fält man vill åt? tex "select faltnr1 from my_table..." ??

Ja det stämmer, men skrev bara det där som ett exempel för att förklara vad jag menade
Det jag vill få fram är att om man inte gör en fråga unik så har databasen cachat den och det ökar hastigheten rejält.
Oavsett om det är select * eller select faltnr1.

En unik fråga:
select faltnr1 from my_table where my_id=100

En fråga som inte är unik, och därmed blir cached:
select faltnr1 from my_table where my_id=?

Sen låter du databasen efter den läst din fråga populera värdet för ditt ?

Permalänk
Legendarisk
Skrivet av nesohc:

Ja det stämmer, men skrev bara det där som ett exempel för att förklara vad jag menade
Det jag vill få fram är att om man inte gör en fråga unik så har databasen cachat den och det ökar hastigheten rejält.
Oavsett om det är select * eller select faltnr1.

En unik fråga:
select faltnr1 from my_table where my_id=100

En fråga som inte är unik, och därmed blir cached:
select faltnr1 from my_table where my_id=?

Sen låter du databasen efter den läst din fråga populera värdet för ditt ?

Detta varierar. TS använder MySQL via ext/mysql i PHP och det API:t saknar stöd för prepared statements (använd mysqli eller PDO istället). Dessutom återanvänder inte MySQL prepared statements mellan olika sessioner, och i versioner < 5.1 kan inte prepared statements dra nytta av query cachen. Det är alltså inte säkert att han skulle tjäna något på att använda ett sådant. Kör han bara frågan en gång per anslutning kan det resultera i mer overhead för att initialisera den än för att bara köra frågan som vanligt.

Skrivet av MrCaps:

Din query är inte så säker och du verkar inte avsluta den på ett korrekt sätt.
Jag förstår inte varför du skriver $this>id, antar att $this är en variabel som innehåller ditt id?

Isåfall testa följande:

mysql_query("UPDATE `strider` SET `hitpoints`='$hp' WHERE `id`='$this'");

Om du syftar på sql injection så är det ingen skillnad på era två versioner. Din förlitar sig på PHPs string interpolation och hans använder sig av vanlig concat, men slutresultatet blir detsamma, och i båda fall bör variablerna escapas (såvida han inte går över till ett API med stöd för prepared statements och använder dessa istället). Variabeln $this innehåller en referens till det objekt metoden hör till, och ->id indikerar en property av detta.

Skrivet av Björnen123:

Jag har en mysql query inne i en klassfunktion som är väldigt simpel:

mysql_query('UPDATE strider SET hitpoints=' . $hp . ' WHERE id=' . $this->id);

Scriptet körs på ca. 0.06-0.1 sekunder med linjen och 0.0003 utan. Vad kan problemet vara?
hitpoints och id är båda int(11)

Har du ett index på kolumnen id?

Skickades från m.sweclockers.com

Visa signatur

Abstractions all the way down.

Permalänk
Medlem
Skrivet av Tunnelsork:

Detta varierar. TS använder MySQL via ext/mysql i PHP och det API:t saknar stöd för prepared statements (använd mysqli eller PDO istället). Dessutom återanvänder inte MySQL prepared statements mellan olika sessioner, och i versioner < 5.1 kan inte prepared statements dra nytta av query cachen. Det är alltså inte säkert att han skulle tjäna något på att använda ett sådant. Kör han bara frågan en gång per anslutning kan det resultera i mer overhead för att initialisera den än för att bara köra frågan som vanligt.

Ah, som jag sa i mitt första inlägg så kan jag inte PHP så jag vet inte hur det fungerar med prepared statements.
Men då har jag lärt mig något nytt iaf, tackar

Permalänk

Vet inte precis om jag vill kalla det en otroligt seg query, då en query i en stor tabell kan ta över en sekund om det vill sig illa. Men som redan föreslagits, kolla att du har ett index på kolumnen id.