Wolne wczytywanie podstrony pobieranej poprzez jQuery

Odpowiedz Nowy wątek
2015-01-04 23:28
nowy12345
0

Witam,
rozmawiałem ze znajomym który tworząc swoją stronę wykonuje około 10 zapytań (pobiera zdjęcie, info o przyciskach typu "lubie to" itp.). Pokazywał mi działanie i powiem, że zachrzania (wszystko w ułamek sekundy). Napisałem więc co takiego:

Klasa która łączy się z bazą danych poprzez driver MySQLi w ten sposób:

<?php
class MySQL
{
  protected $dbResult = false;
 
    /*
        $query - zapytanie
        $isErrorDisplayed - czy błąd ma być wyświetlany (default: false)
    */
    function __construct($query, $isErrorDisplayed = false)
    {
        $conn = new mysqli('host', 'user', 'pass', 'database');     // połączenie z bazą danych
 
        if([email protected]$conn->connect_error)                      // jeżeli połączenie jest udane
        {
            @$conn->set_charset($charset);                  // ustawiam kodowanie dla pobieranych danych
            //@$conn->query("SET NAMES {$charset}");            // ustawiam kodowanie dla pobieranych danych
            $this->dbResult = @$conn->query($query);        // wysyłam zapytanie i pobieram wynik (w tym ilość rekordów i pól)
 
            if($conn->error && $isErrorDisplayed)       // wyświetla błąd zapytania (w zależności od $isErrorDisplayed)
            {
                exit($conn->error);
            }
 
        } elseif ($isErrorDisplayed) {                  // wyświetla błąd połączenia (w zależności od $isErrorDisplayed)
            exit($conn->connect_error);
        }
    }
 
    /* Funkcja zwraca wynik zapytania */
    public function response()
    {
        return $this->dbResult;
    }
}
?>

Pobranie 20 zdjęć (oddzielne zapytania):

<?php
include_once("class.MySQL.php");
 
for($i=1; $i<=20; $i++)
{
$img = new MySQL("SELECT image FROM dbImages WHERE `id` = '{$i}'");
// na razie pomijam wyświetlanie bo ono nie ma znaczącego wpływu na prędkość wczytywania
}
?>

Strona wczytuje się w 15 sekund... Gdy zmienię kod na taki:

<?php
include_once("class.MySQL.php");
 
$nr = array();
for($i=1; $i<=20; $i++) { array_push($nr, $i); }
 
$ids = implode("','", $nr);
$img = new MySQL("SELECT image FROM dbImages WHERE `id` IN('{$ids}')'");
// na razie pomijam wyświetlanie bo ono nie ma znaczącego wpływu na prędkość wczytywania
}
?>

Strona wczytuje się w niecałe 2 sekundy. Z czym to jest związane? Z moim serwerem (używam WebServ)? Z tym, że musiał mi ściemniać w tym co mówił, albo jego kod wysyła jedno "zgrupowane" zapytanie do bazy? Z tego co wiem on wszystko ma na Amazonie.

Proszę o poradę, ponieważ obecnie muszę przerabiać całą stronę, ponieważ wszystko jest oparte na założeniu, że z początku postu (mój błąd). Proszę też o poradę jaki serwer/framework/metodę działania wybrać, aby było wszystko ok.

Pozostało 580 znaków

2015-01-05 00:17
1

Zacznijmy może od tego, że za samo tworzenie osobnej instancji MySQLi na każde zapytanie ten wątek powinien trafić do perełek, a Ty powinieneś dostać batem po tyłku.

Proszę też o poradę jaki serwer/framework/metodę działania wybrać, aby było wszystko ok.
Yii/Zend/CakePHP, wszystko, bylebyś nie pisał własnego frameworka nie mając o tym pojęcia :v

Btw, komentarze stawiaj przed linijką, a nie w tej samej.


edytowany 5x, ostatnio: Patryk27, 2015-01-05 00:22

Pozostało 580 znaków

2015-01-05 07:51
nowy12345
0

No dobra, zjebka jest xD A co z resztą?

Co do frameworka to chodzi mi o to, czy jak użyję jakiegoś to ten przykład wykona się szybciej (czyli nie będzie mojego kodu do połączenia z bazą danych)?

Czy masz jakiś przykład poprawnego tworzenia klasy mysql/mysqli? Czy użycie jej spowoduje przyspieszenie pracy programu? Czy jednak to też kwestia serwera?

Pozostało 580 znaków

2015-01-05 08:14
Złoty Lew
1

Ja bym zastosował PDO

// $array - lista otrzymanych id
$conn = new PDO('mysql:host=host;dbname=database', 'user', 'pass');
$pdo -> setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$stmt = $pdo -> prepare ("SELECT image FROM dbImages WHERE `id` IN(:nr1, :nr2, ... :nr20)");
 
$stmt -> bindValue(':nr1', $array[0], PDO::PARAM_INT);
...
$stmt -> bindValue(':nr20', $array[19], PDO::PARAM_INT);
$stmt -> execute();
$results = $stmt -> fetch();
 
return $results;

Pozostało 580 znaków

2015-01-05 10:00
0

Czy masz jakiś przykład poprawnego tworzenia klasy mysql/mysqli? Czy użycie jej spowoduje przyspieszenie pracy programu? Czy jednak to też kwestia serwera?

$mysql = new MySQL(...);
 
$result1 = $mysql->query('select cośtam');
$result2 = $mysql->query('select cośtam_innego');
...

Czyli tworzysz raz i wykorzystujesz do wszystkich potrzebnych zapytań.

Frameworki przeważnie mają dodatkowo jakieś buildery w stylu:

$result1 = App::buildQuery()->select('cośtam')->from('tabela')->execute();

Oraz różnej maści cache, więc może to wyglądać na przykład tak:

$images = SqlCache::fetch('images');
 
if ($images === null) {
  $result = $mysql->query('select cośtam');
  /* tutaj magia, stworzenie tablicy $images */
  SqlCache::save('images', $images);
}

I wtedy mamy zapisaną listę naszych obrazków do pamięci podręcznej, przez co zapytanie wykonane zostaje przypuśćmy raz na dzień, na tydzień. Chyba że są to obrazki, które są często zmieniane - wtedy nie warto bawić się w cache :P


edytowany 1x, ostatnio: Patryk27, 2015-01-05 10:01

Pozostało 580 znaków

2015-01-05 22:04
nowy12345
0

Rozumiem, swój błąd - dzięki :)

Mimo wszystko nasuwa mi się trochę pytań. Może zacznę od tego co robię. Piszę "mały" sklep internetowy - nie do sprzedaży, ani do konkretnej pracy tylko dla nauki - w którym (po słowach tego kolegi) przyjąłem taką strategię:

  1. Wchodząc na stronę jakiejś kategorii (np.: Owoce) pobieram produkty w tej kategorii.
  2. Zakładając, że pobrałem 20 produktów na stronę, a każdy z nich ma 5 zdjęć wykonałem to w ten sposób:
    a) SELECT * FROM dbProdukty WHERE id IN (tutaj_numery_id)
    b) wykonuję pętlę po wszystkich produktach tworząc obiekt dla każdego z nich
    c) w klasie Produkt pobieram z bazy zdjęcia dla danego produktu

Czyli wykonuję 21 zapytań do bazy. W takim razie mam dwie metody na przyspieszenie tego działania:

  • pobranie od razu wszystkich produktów i ich zdjęć z bazy i przetworzenie całości dopiero po otrzymaniu
  • utworzenie jednej instancji (wzorzec Singleton), która raz się łączy i pobiera wynik poprzez każdorazowe wywołanie query() - przykład kodu poniżej (pisałem z głowy - kod nietestowany):
<?php
class MySQL
{
  private static $instance = NULL;
  private $conn;
 
    /*
        $query - zapytanie
        $isErrorDisplayed - czy błąd ma być wyświetlany (default: false)
    */
    function __construct()
    {
        if(empty(self::$instance))
        {
            $this->$conn = new mysqli('host', 'user', 'pass', 'database');      // połączenie z bazą danych
            if([email protected]$this->conn->connect_error)                                    // jeżeli połączenie jest udane
            {
                @$this->conn->set_charset('utf8');                  // ustawiam kodowanie dla pobieranych danych
                //$this->conn->query("SET NAMES utf8");             // ustawiam kodowanie dla pobieranych danych
                self::$instance = $this;                            // instancja
            } else {
                exit($conn->connect_error);                         // wyświetla błąd połączenia
            }
 
        } else {
            $this = self::$instance;
        }
    }
 
    public function query()
    {
        // wyświetla błąd zapytania
        if($this->conn->error) exit($this->conn->error);
 
        // wysyłam zapytanie i pobieram wynik (w tym ilość rekordów i pól)
        return @$conn->query($query);
    }
 
    public function __destruct()
    {
        $this->$conn->close();
        // lub mysqli_close($this->$conn);
    }
?>
  • Pytanie tylko o ile przyspieszy mi pracę jedno połączenie z bazą i tylko wysyłanie zapytań co jakiś czas?
  • I jeszcze jedno. Mam pliki językowe związane ze stroną i z opisem zdjęć - czy wszystko trzymać w bazie danych, czy część odpowiedzialną za tłumaczenie strona na serwerze, a w bazie danych opisy zdjęć?

Pozostało 580 znaków

Odpowiedz
Liczba odpowiedzi na stronę

1 użytkowników online, w tym zalogowanych: 0, gości: 1, botów: 0