Jump to content
php.lv forumi

Banneris ar click noteicēju


So sick!

Recommended Posts

Man nepieciešams skripts, kurš uzģenerēs kodu pēc lietotāja pieprasījuma. Lietotājs kodu ieliek savā lapā un parādas banneris ar linku piem. http://lapa.lv/b.php?banner=big&lid=1 un uzspiežot uz bannera lietotājam ar id 1 pieskaitās 5punkti. Kodēt es māku, bet man vajag arī izdomāt kā lai izdara tā, ka ja no viena ip 2x uzspiež, tad 2. reizē nepieskaita tos 5punktus?

Tātad palīdziet man lūdzu ar šīm 2 lietām:pats skrips, ip aizsardzība.

Aptuveni ka varetu izskatities:

<?
connect_to_db();
$lid = $_GET['lid'];
$banner_izm = $_GET['banner'];
$ip = $_SERVER['REMOTE_ADDR'];
$date = date(Y-m-d);

$r = mysql_query("SELECT * FROM advertise, users WHERE users.id=$lid AND advertise.izm=$banner_izm");
$row = mysql_fetch_array($r);
mysql_query("INSERT INTO advertise (ip,date,lid) VALUES ($ip, $date, $lid)");
$points = $row['points'];
$points_new = $points+5;
mysql_query("UPDATE users SET points=$points_new WHERE id=$lid");
//If ip fignjas te..
//Redirekts uz indexu talak, bet to nerakstishu..


?>

Edited by So sick!
Link to comment
Share on other sites

Kā lai pārbauda par to ip... Es domāju ka kaut kā šādi ne?

<?
$d = mysql_query("SELECT ip,date FROM advertise WHERE ip=$ip");
$d2 = mysql_result($d);
$date = $d2['date'];
if($date > date(Y-m-d)){
//pievieno punktus
}else{
//nepievieno punktus
}
?>

Edited by So sick!
Link to comment
Share on other sites

$d = mysql_query("SELECT ip,date FROM advertise WHERE ip=$ip");
?>

spriezjot pec shii tu ip glba kaa stringu ??

ja jaa tad

1. pie parbaudes trukst pedinju ip='$ip'");

2. ip labak ir glabat kaa INT unsignet, lai parverstu UZ/ NO izmanto SQL f-jas

INET_ATON() un INET_NTOA()

Link to comment
Share on other sites

Es jav visu esmu izdomājis.. Dabūšu ip un pārveidošu par INT ar INET_ATON. Tad to INT saglabāšu datubāzē un pārbaudi veikšu pārveidojot apmeklētāja ip arī par cipariem. Ja tādi cipari jav būs datubāzē ar šodienas datumu, tad nepieskaitīs punktus, bet ja nebūs ar šodienas datumu, tad pieskaitīs.. :)

Link to comment
Share on other sites

ip labak ir glabat kaa INT unsignet, lai parverstu UZ/ NO izmanto SQL f-jas INET_ATON() un INET_NTOA()

un kur palika pamatojums? ;)

 

tā konvertēšana tač ir papildus slodze mysql serverim un papildus darbs programmētājam (sīkums, bet tomēr)

vai tiešām pāris baitu dēļ tas ir vajadzīgs? anyway tas ir ļoti mazs procents no kopējā storage (pārējiem datiem dažādos teksta laukos)

 

man liekas, ka mūdienās vieta vairs nav problēma (hdd,ram ir lēti) taču servera jauda, kas ir vajadzīga, lai vienlaicīgi apkalpotu daudz lietotājus gan pagaidām vēl nav pārpilnībā. es drīzāk atslogotu cpu no konvertācijas (bez kuras var iztikt) un rakstītu Ip varchar(15)

Link to comment
Share on other sites

un kur palika pamatojums? ;)

Tieshi delj noslodzes, jo

vai saliidzinat 15 zimju Char lauku , vai 1 Integer, kas notiek Vismaz 15X atrak (Vismaz!!!)

IP adreses parversana Integer ir diezgan primitiiva operacija, vismaz Kompim noteikti

(reali taa ir vienkarsha baitu parcelsana, kas aiznjems ~~~4 Procha taktiis (ja pat tik daudz)

Ja vel laukus tiek indekseets tad vietas ieguvums buus arii vismaz 15X reizju lielaks ( vai indeksee CHAR vai Integer)

--

Kavacky nevis 15 Bet gan 16( viens baits faktiskajam lauka garumam), jo diezvai vinsg glabas CHAR laukaa ( ja parejie buus Warchar tad CHAR vispar neies )

Bet nu vieta tiesam nebuutu tas butiskakais, ja vien ieraksti nesniegsies miljonos

 

So sick! --> tos INET_ATON() un INET_NTOA() izmanto pa taisno Kverijaa,

pat nekas nav japarveido ar PHP ;)

UPDATE xx SET cc=cc+1 WHERE ip=INET_NTOA('123.123.123.0')  
un 
SELECT INET_ATON(ip) AS gatava_ip FROM xx

un ja kas PHP arii ir liidzigas f-jas ...

Edited by Grey_Wolf
Link to comment
Share on other sites

Matemātiskās operācijas labāk padodas uz int tipiem.

 

PS: 4 vs 15 baiti - 3.75 reižu konstants ietaupījums arī nav slikti.

iekš "WHERE ip=$ip" kur te ir matemātiska operācija? salīdzināšana? ok, lai tā būtu

konstants ietaupījums? hmm, man gan drīzāk liekas, ka mainīgs (atkarībā no datiem)

pašam ar asm nav pieredzes, bet man liekas, ka divu 4x baitīgu integeru salīdzināšana varētu būt 1x cpu instrukcija, savukārt 15x baitīgus stringus iespējams salīdzina pa baitam: kamēr tie ir vienādi, tikmēr iet uz priekšu, līdz visi baiti ir salīdzināti. bet varbūt arī stringus salīdzina, cpu reģistros katrā taktī uzreiz iedzenot pa 4x baitiem? tādējādi stringu salīdzināšanai vajadzētu būt ilgākai par integeru salīdzināšanu tikai tad, ja abu stringu pirmie baiti sakrīt, jo tad ir jāveic vairākas low level salīdzināšanas

 

whatever, nav ko daudz teoretizēt. labāk skatāmies, cik ātri viss notiek reālā darbībā

$gnTime = 0;
function utime() {list($sSecU, $sSec) = explode(' ', microtime()); return $sSec + $sSecU;}  // izdod pašreizējo laiku: sekundes + mikrosekundes (aiz "komata")
function timerSet() {global $gnTime; $gnTime = utime();}
function timerGet() {global $gnTime; return round(utime() - $gnTime, 6);}
function timerEcho($sInfo = '') {printf('%s%.4f<br />', $sInfo, timerGet());}  // parāda laiku ar precizitāti līdz 100 mikrosekundēm (ilgākām darbībām). lielākas precizitātes mērījumiem desmitos mikrosekunžu (vai vēl mazāk) ir jāņem vērā arī pašas funkcijas izsaukuma laiks (tb tad būtu jāaprēķina function call overhead)

function qs($s) {  // sagatavo stringu priekš sql query
return is_null($s) ? 'NULL' : "'" . mysql_real_escape_string($s) . "'";
}
function go($sSql) {  // mysql query ar error reportingu
$h = mysql_query($sSql) or die('<b>mysql error ' . mysql_errno() . ':</b> ' . mysql_error() . '<br /><b>query:</b> ' . substr($sSql, 0, 1000));
return $h;
}

function ipRand() {return rand(0, 255) . '.' . rand(0, 255) . '.' . rand(0, 255) . '.' . rand(0, 255);}
function ipLoad() {  // izveido/ielādē testa datus: 100 000 random ip adreses 3x dažādos tabulas laukos
$h = fopen('load.sql', 'w');
fwrite($h, 'INSERT t (Ip, Ip2, Ip3) VALUES (');
for ($i = 0; $i < 100000; $i++) {
	$sIp = ipRand();
	fwrite($h, ($i ? '),(' : '') . qs($sIp) . ',' . qs($sIp) . ',' . sprintf('%u', ip2long($sIp)));
}
fwrite($h, ')');
fclose($h);

go('DROP TABLE IF EXISTS t');
go('CREATE TABLE t (Ip varchar(15) NOT NULL, Ip2 char(15) NOT NULL, Ip3 int UNSIGNED NOT NULL) ENGINE=MyISAM');
go('ALTER TABLE t ADD INDEX (Ip)'); go('ALTER TABLE t ADD INDEX (Ip2)'); go('ALTER TABLE t ADD INDEX (Ip3)');
//go('SET GLOBAL max_allowed_packet = 104857600');  // vajag priekš lieliem query, taču uz hostiem var nebūt tiesību mainīt šo settingu. tad atliek localhost
go(file_get_contents('load.sql'));
}
function ipLoadTimer() {  // ielādē datus un parāda, cik tas paņem laiku
timerSet();
ipLoad();
timerEcho('IP ielāde: ');
}
function ipSelTimer() {  // selectē ip no dažādiem laukiem, lai noskaidrotu, no kura to var izdarīt visātrāk
list($sIp) = mysql_fetch_row(go('SELECT Ip FROM t LIMIT ' . rand(0, 99999) . ',1'));  // paņem random ip, kuru pēc tam "meklēs"

timerSet();
$h = go('SELECT * FROM t WHERE Ip = ' . qs($sIp));
timerEcho('Ip select: ');

timerSet();
$h2 = go('SELECT * FROM t WHERE Ip2 = ' . qs($sIp));
timerEcho('Ip2 select: ');

timerSet();
$h3 = go('SELECT * FROM t WHERE Ip3 = ' . sprintf('%u', ip2long($sIp)));
timerEcho('Ip3 select: ');

timerSet();
$h4 = go('SELECT * FROM t WHERE Ip3 = INET_ATON(' . qs($sIp) . ')');
timerEcho('Ip3 select2: ');
}

ini_set('max_execution_time', 300);
ipLoadTimer();  // izpilda 1x, lai ielādētu testa datus (pēc tam aizkomentē)
ipSelTimer();  // izpilda daudzreiz, kamēr iegūst pietiekami ticamu vidējā laika novērtējumu
/*
aptuvens vidējais rezultāts uz mana pc:

// 10 000 rindas
IP ielāde:   0.7000
Ip select:   0.0008
Ip2 select:  0.0008
Ip3 select:  0.0006
Ip3 select2: 0.0006

// 100 000 rindas
IP ielāde:   6.0000
Ip select:   0.0008
Ip2 select:  0.0008
Ip3 select:  0.0006
Ip3 select2: 0.0006

// 1 000 000 rindas (brīžiem diezgan nestabili rezultāti, tāpēc svārstīgākajiem rezultātiem ir laika intervāls, nevis viens aptuvenais laiks)
IP ielāde:   45s (load.sql izveidošana) + 2min (load.sql -> mysql)
Ip select:   0.0030
Ip2 select:  0.0030 - 0.0300
Ip3 select:  0.0025
Ip3 select2: 0.0025
*/

jāsaka gan, ka 1 000 000 rindas izdevās iedabūt db tikai no komandrindas: > mysql -u root -p < load.sql

INSERTam pieliekot priekšā db selektu: USE test;

jo, ieraugot ~43MB lielu query, mysql vnk aizbēga "MySQL server has gone away" :D:D:D, neskatoties uz to, ka max_allowed_packet ir uzlikts 100MB ;)

turklāt pat no komandrindas tas nebija tik gludi. tas tādēļ 512MB RAM, ar ko šim testam ir par maz, jo load laikā mysqld-nt.exe izaug pāri par 500MB (RAM + VM). vispār, kad tabulas izmērs aiziet desmitos MB (pāri par 100 000 rindām atkarībā no testa datu apjoma), tad es to vairs nevaru normāli notestēt, jo ir nestabili rezultāti, ram pārslodze...

 

secinājumi:

1) ieguvums no Ip int UNSIGNED salīdzinot ar Ip varchar(15) ir tiešām mikroskopisks: tabulām no 10k - 100k rindām tas ir 100 līdz 200 mikrosekundes (turklāt tas ir uz parasta ne pārāk jauna mājas kompja P4 2.6GHz, 512MB DDR). vienīgi sākot no miljons rindām parādās kāda milisekunde atšķirība! :D

mēģinot padarīt šo testu objektīvāku, atsevišķi notestēju arī mazāk rindas (10k) taču garākas - ar extra lauku varchar(200) ar random tekstu. un kā izrādījās, selectus tas nekādi neietekmēja (skaidrojums: WHERE skatās iekš index, un šajā gadījumā pašas tabulas izmēram nav nozīme)

2) atšķirību starp Ip varchar(15) un Ip char(15) nevarēja pamanīt

3) tāpat arī tā īsti nevarēja pamanīt atšķirību starp ip konvertēšanu php/mysql pusē ar ip2long()/INET_ATON()

4) atšķirība starp 10k un 100k rindām arī nebija īpaši jūtama (10k rindām daži rezultāti epizodiski bija mazāki, nekā mēdz būt mazākie rezultāti 100k rindām, taču vidēji tas pats)

 

anyway Vilks, tā jau tu domā pareizi, ka ar int ir ātrāk. tikai tas ieguvums ir tik niecīgs, ka to vispār var neņemt vērā. tas tā varētu būt tāpēc, ka mysql iekšpusē ir uz viskko nooptimizēts. un lai arī ārēji/teorētiski liekas, ka vienam risinājumam vajadzētu būt daudz ātrākam, taču praksē tas tā var nebūt...

gan jau ka ir pielietojumi, kur šāds ip adreses formāts dod jūtamākus ieguvumus, taču šis nav tas gadījums ;) protams, pastāv arī maza varbūtība, ka kādam citam šis tests dotu pavisam citus rezultātus nekā man un tad jau sazin, kur būtu patiesība... :D:D:D

 

btw, pa "Discovery Channel" iet tāda raidījumu sērija "MythBusters", kur džeki lauž vienu stereotipu pēc otra... vnk šitais te sāk atgādināt to raidījumu :P

 

kr4 iesaku praktiski pārbaudīt lietas. datorzinātne ir gan eksakta, gan empīriska, tāpēc vajag experimentēt, nevis tikai gudri spriedelēt ;)

Link to comment
Share on other sites

Esi pārliecināts? Es kautkā šaubos par šo apgalvojumu - es teiktu, ka ieguvums labi ja būs 1.5x

nu Ok. ne 15X reizju bet nu krietni.

Jo

Salidzinat 15X + 1 (garuma notiksana) baitus vai 4 ir tomer atskjiriiba ..

Dizvai nepiekritisi ka pat 1 simbola Char un 1 Integer atrashana buus par labu Integer

Tas taa nevelos ipashi ielaisties 'Religiska' disputaa...

------

gan jau ka ir pielietojumi, kur šāds ip adreses formāts dod jūtamākus ieguvumus, taču šis nav tas gadījums ;) protams, pastāv arī maza varbūtība, ka kādam citam šis tests dotu pavisam citus rezultātus nekā man un tad jau sazin, kur būtu patiesība... :D:D:D

Aha ir gan cits pielietojums ;)

Saucas DNS serveri ..

--

Neba 10-100Rindinjas ir nopietnis raditajs DB tabulai ..

Ja lapa buus peitiekami apmekleta, tad atri vein savakas taas 1M rindinjas, un tad jau rezultatas buus juutams..

Piedevam ier slikta prakse nepareizi glabat datus..

Jo iesakot ka CHAR( Warchar) ir labakais veids kaa glabat IP tad ....

( sliktie vardi izlaisti, bet saglabajas domas no tiem kam kautko tadu naksies pielabot, {nedod dies` konvertet daudzu M garu DB tabli..} )

---

Edited by Grey_Wolf
Link to comment
Share on other sites

Jo

Salidzinat 15X + 1 (garuma notiksana) baitus vai 4 ir tomer atskjiriiba ..

Bet tas jau ir tikai tad, ja datus salīdzina pa tiešo.

Ja lauki ir indeksēti, tad tie netiek salīdzināti pa tiešo - tiek salīdzināti to heši. Un integera hešs ir tikpat liels/ātrs kā stringa hešs salīdzināšanā.

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
×
×
  • Create New...