[PHP] Snel ID opzoeken adhv een IP

Pagina: 1
Acties:

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 08-09 17:10
Ik moet héél vaak een ID aan de hand van een IP opzoeken. De IP-ranges en ID's staan in een tabel in de database, samen met een tijd-range. Zo kan een IP-range op verschillende tijdstippen een verschillend ID hebben.

De tabel:
code:
1
2
3
4
5
6
7
8
9
+---------------+----------------------+------+-----+---------+-------+
| Field    | Type            | Null | Key | Default | Extra |
+---------------+----------------------+------+-----+---------+-------+
| id        | smallint(5) unsigned |    |     | 0    |   |
| startip    | int(10) unsigned     |   |     | 0    |   |
| endip    | int(10) unsigned     | |     | 0    |   |
| startdatetime | datetime       | YES  |     | NULL    |    |
| enddatetime   | datetime       | YES  |     | NULL    |    |
+---------------+----------------------+------+-----+---------+-------+

De code die ik nu gebruik om een ID op te zoeken:
PHP:
1
<?// Get the hosts$result = mysql_query ("SELECT id, startip, endip, startdatetime, enddatetime FROM hosts ORDER BY (endip - startip)");while ($temp = mysql_fetch_array ($result)) { $hosts["$temp[1],$temp[2],$temp[3],$temp[4]"] = $temp[0];}for ($i = 0; $i < count($ips); $i++) {  getid ($ips[$i]["IP"], $ips[$i]["timestamp"], $hosts);  // Code gestripped die het ID verder verwerkt}function getid ($longip, $timestamp, $hosts) {  $longip = explode (".", $longip);  $longip = ($longip[0] * pow (256, 3)) + ($longip[1] * pow (256, 2)) + ($longip[2] * 256) + $longip[3];  $timestamp = mktime (substr ($timestamp, 11, 2), substr ($timestamp, 14, 2), substr ($timestamp, 17, 2), substr ($timestamp, 5, 2), substr ($timestamp, 8, 2), substr ($timestamp, 0, 4));  foreach ($hosts as $hostdata => $id) {    $hostdata = explode (",", $hostdata);    if (($longip >= $hostdata[0]) &amp;&amp; ($longip <= $hostdata[1]) &amp;&amp; ($timestamp >= $hostdata[2]) &amp;&amp; (($timestamp <= $hostdata[3]) || ($hostdata[3] == 0))) { return $id; }  }  return 0;}?>

$id ziet er dus bijvoorbeeld zo uit: $id[14]["IP"] = 192.168.0.1 en $id[14]["timestamp"] = 123456;
De IP's zijn in de database opgeslagen als longip. Oftewel: 192*256^3 + 168*256^2 + 0*256 + 1;

Als ik deze functie 4000 keer aanroep achter elkaar duurt het véél te lang. Ik ben gisteravond van 9 tot 5 bezig geweest hem te verbouwen en te verbouwen.. Maar sneller werd ie niet :'( Iemand anders ideeën?

  • chem
  • Registratie: Oktober 2000
  • Laatst online: 27-08 13:53

chem

Reist de wereld rond

waarom niet alles in je mysql database doen?
select id from hosts where (ip between $start and $stop) and ($time between startdatetime and enddatetime);

Klaar voor een nieuwe uitdaging.


  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 08-09 17:10
Omdat je dan 4000 query's krijgt, en da's nóg langzamer

  • DizzyWeb
  • Registratie: Februari 2001
  • Laatst online: 06-09 00:14

DizzyWeb

Ondertiteld

Mee eens. Je zal moeten proberen om mySQL het werk te laten doen. Als je met een paar queries kan doen wat je nu met duizenden queries doet, dat kan weinig anders als een enorme snelheids boost geven...

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 08-09 17:10
Ik gebruik nu juist geen 1000en queries, maar 1tje!

  • DizzyWeb
  • Registratie: Februari 2001
  • Laatst online: 06-09 00:14

DizzyWeb

Ondertiteld

Op zondag 21 april 2002 12:08 schreef elviver het volgende:
Ik gebruik nu juist geen 1000en queries, maar 1tje!
Excuus :) Helaal scheel gelezen, tis nog vroeg :P

*denkt ff na*

  • GraasGast
  • Registratie: Oktober 2000
  • Laatst online: 03-09 17:11

GraasGast

Analogue Heaven

Op zondag 21 april 2002 12:07 schreef elviver het volgende:
Omdat je dan 4000 query's krijgt, en da's nóg langzamer
Onzin. Met chem's oplossing heb je maar 1 query nodig, en krijg je maar 1 resultaat terug, ipv de 4000 van nu :P

  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 08-09 17:10
Op zondag 21 april 2002 12:44 schreef GraasGast het volgende:

[..]

Onzin. Met chem's oplossing heb je maar 1 query nodig, en krijg je maar 1 resultaat terug, ipv de 4000 van nu :P
Maar ik roep die getid-functie 4000 keer aan.. 4000 krijg ik een IP te controleren. Dan moet ik toch 4000 keer een query doen?

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 20:58

Janoz

Moderator Devschuur®

!litemod

Het lijkt me allemaal trouwens een stuk sneller werken als je je ip's gewoon in een getal opslaat (wat het eigenlijk ook is.. een 32bits getal) Dan hoef je ook geen explode ed meer aan te roepen.

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


  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 08-09 17:10
Doe ik ook.. Alleen in de logs wordt het nog wel met .'en opgeslagen.. En zoals gezegd.. Ik kan de logs niet veranderen, dwz, ik kan ze niet anders "maken" omdat een programma dat doet..

Ik ga even kijken hoe het gaat met tijdranges per dag...

  • LuCarD
  • Registratie: Januari 2000
  • Niet online

LuCarD

Certified BUFH

Je doet wel een beetje vaag of ligt dat aan mij?

1/ Kijk eens naar de functie www.php.net/long2ip en www.php.net/ip2long

2/ In de functie heb je gebruik je mktime met een heleboel substr ????
Dat is een beetje onzinnig.... Als je absoluut timestamps wilt hebben uit de database kan je dat makkelijker via de query doen.
code:
1
select UNIX_TIMESTAMP(<DATETIMEFIELD>)

3/ In jouw for lus gebruik je count($ips) in de voorwaarde gebruik een variable om deze voorwaarde te "cachen" want nu word count elke loop weer aangeroepen.

Programmer - an organism that turns coffee into software.


  • DRvDijk
  • Registratie: Juni 2001
  • Laatst online: 08-09 17:10
Op zondag 21 april 2002 15:28 schreef LuCarD het volgende:
1/ Kijk eens naar de functie www.php.net/long2ip en www.php.net/ip2long
Deze functies geven niet dezelfde waarden terug als MySQL-funties INET_ATON en INET_NTOA.
2/ In de functie heb je gebruik je mktime met een heleboel substr ????
Dat is een beetje onzinnig.... Als je absoluut timestamps wilt hebben uit de database kan je dat makkelijker via de query doen.
code:
1
select UNIX_TIMESTAMP(<DATETIMEFIELD>)
Dat is om een timestamp te maken van de tijden die uit de log-bestanden komen. Die staan in het formaat YYYY-MM-DD HH:MM:SS en wil ik in een UNIX_TIMESTAMP formaat hebben. Als ze al in de mysql-db zouden staan, zou het inderdaad makkelijk zijn, maar dat is hier dus niet het geval.
3/ In jouw for lus gebruik je count($ips) in de voorwaarde gebruik een variable om deze voorwaarde te "cachen" want nu word count elke loop weer aangeroepen.
Ja oke, maar da's alleen om aan te geven hoe vaak deze functie herhaald moet worden. In de echte code (veel langer en onzinnig om hier te posten) doe ik het sowiezo anders, niet met een count.
Pagina: 1