Connection to MySQL inside fooreach loop slow down my php page

1.2k views Asked by At

I have appointment script in php + mysql.

in the script I have 6 column and every column have 64 row that is equal to 384 field. For every field I have one mysql_query connection, that mades 384 connections to MySQL. is there any way to make this script more effective and faster??? Also i want to add that this script run on Xeon 3.4ghz 4 core 8gb ram server and i have delay for this page about 20-25 sec. but on another pages where I dont use loop I have very fast results even if i list few hundreds of row.

This is my code:

$listebolum=mysql_query("SELECT * FROM bolum WHERE randevu='ok' AND sube='".$_SESSION[ksube]."' ORDER BY id ASC");
while($listeboluml=mysql_fetch_array($listebolum)) {
    $basla=$danas;
    echo "<div style=\"position:relative; width:".$sirina."%; float:left; border-right:solid 1px #9a4b9d;\">";
    for($ra=$danas; $ra<$danasson; $ra=($ra+900)) {

        $uzmirandevu=mysql_query("SELECT randevu.id AS rid, randevu.bitis AS rbitis, randevu.baslama AS rbaslama, randevu.notum AS rnotum, randevu.hizmetler AS rhizmetler, musteri.ad AS mad, musteri.soyad AS msoyad FROM randevu LEFT JOIN musteri ON randevu.musteri=musteri.id WHERE randevu.baslama='".$basla."' AND randevu.sube='".$_SESSION[ksube]."' AND randevu.bolum='".$listeboluml[id]."'");
        $uzmirandevul=mysql_fetch_array($uzmirandevu);
        $yukseklik=(((($uzmirandevul[rbitis]-$uzmirandevul[rbaslama])/900)*26)-1);
        echo "some data from databse"; 
        $basla=$uzmirandevul[rbitis];
    }
}
echo "</div>";
}

MySQL structure:

`randevu` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`baslama` int(10) unsigned NOT NULL,
`bitis` int(10) unsigned NOT NULL,
`musteri` int(10) unsigned NOT NULL,
`personel` smallint(5) unsigned NOT NULL,
`notum` varchar(512) COLLATE utf8_unicode_ci NOT NULL,
`durum` char(2) COLLATE utf8_unicode_ci NOT NULL,
`sube` smallint(4) unsigned NOT NULL,
`bolum` smallint(4) unsigned NOT NULL,
`hizmetler` varchar(256) COLLATE utf8_unicode_ci NOT NULL,
`zaman` int(10) unsigned NOT NULL,
`rgun` tinyint(2) NOT NULL,
`ray` tinyint(2) NOT NULL,
`ryil` smallint(4) NOT NULL,
`guncelleme` int(10) NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ;
1

There are 1 answers

4
Nic Wortel On BEST ANSWER

Because your code isn't written in English it is a bit hard for me to understand it, but I advise you to read a bit about the N+1 problem. You can probably remove the second query from the loop in order to cut down your SQL queries. This is called eager loading.

Here is an example:

SELECT * FROM authors // first query

foreach ($authors as $author) {
    SELECT * FROM books WHERE author_id = $author->id // second query
}

With 10 authors, this runs just fine. But with 100 authors, you are running 101 queries: 1 to get the list of authors, and then 1 for every author. In other words, more authors means more queries and therefor a longer loading time.

You can speed things up by removing the second query from the foreach-loop:

SELECT * FROM authors // first query

$author_ids = array();
foreach ($authors as $author) {
    $author_ids[] = $author->id; // add author id to array
}

$author_ids = implode(',', $author_ids); // create a list of comma-seperated ids

SELECT * FROM books WHERE author_id IN ($author_ids) // second query

foreach ($authors as $author) {
    // link books to authors
}

This way you use one query to retrieve all the books, and then you use PHP to link books to the right authors.

It is a bit more complicated, but it reduces the number of SQL queries to 2. This is obviously still very simplistic, but it should give you an idea of the concept.