Оптимизация обработки страниц путем создания расширенного SQL-запроса

У меня есть этот странный код на сайте. Он получает все записи (упорядочение по порядку), затем создает какой-то стек и ограничивает отображаемые записи до 10. Однако, если записей более 200, это занимает слишком много времени, потому что обрабатывает всю таблицу вместо 10.

Используемые значения:

$int_ilosc_na_strone = 10;
$liczba_wierszy = 200;
Podzial_na_podstrony::get_limit_object($int_ilosc, $int_ilosc_na_strone) = 10;
$order = NULL;


public function produkty_kat($adres, $liczba_wierszy, $int_ilosc_na_strone) {
        require_once('lib/Podzial_na_podstrony.class.php');

        $rozloz = explode("/", $adres);
        $id = $rozloz[2];

        $order = $this->podaj_order($adres, 'kategorie');
        if (empty($order)) {
            $order = 'produkty.pozycja ASC';
        }
        if ($order=='price') {
            $order = "produkty.cena ASC";
        }
            $firstack = $this->database->pobierz("SELECT id FROM subkategorie WHERE kategorie_id = '$id' ORDER BY pozycja");
            foreach($firstack as $firstack)
            {
                $stack = $this->database->pobierz("SELECT id FROM sub_subkategorie WHERE subkategorie_id = '{$firstack['id']}' ORDER BY pozycja");
                foreach($stack as $stack)
                {
                    $prods[] = $this->database->pobierz("SELECT produkty.id FROM produkty, przyporzadkowania, stany_magazynowe, gk_grupy_produkty WHERE stany_magazynowe.produkty_id=produkty.id AND produkty.id=przyporzadkowania.produkty_id AND przyporzadkowania.sub_subkategorie_id={$stack['id']} AND produkty.widoczny='1' AND produkty.id = gk_grupy_produkty.id_produktu AND gk_grupy_produkty.id_grupy=$this->int_id_grupy AND gk_grupy_produkty.towar_widocznosc=1 GROUP BY produkty.pozycja ORDER BY $order");
                }
                $temp = array();
                foreach($prods as $o)
                {
                    foreach($o as $o)
                    {
                        $temp[] = $o;
                    }
                }
            }
            $temp2 = array();
            foreach($temp as $o)
            {
                $temp2[] = $o;
            }
            $wynik = $temp2;

            $int_ilosc = count($wynik);
            $this->int_liczba_wierszy = $int_ilosc;
            $obj_limit = null;
            if ($int_ilosc_na_strone > 0) {
                $obj_limit = Podzial_na_podstrony::get_limit_object($int_ilosc, $int_ilosc_na_strone);
            }
            $temp = array();
            $c = 0;
            foreach($wynik as $v)
            {
                if(is_object($obj_limit))
                {
                    if($c >= $obj_limit->min && $c < ($obj_limit->min + $obj_limit->max))
                    {
                        $temp[] = $v;
                    }
                    else if($c == ($obj_limit->min + $obj_limit->max))
                    {
                        break;
                    }
                }
                else
                {
                    $temp = $wynik;
                    break;
                }
                $c++;
            }
            $paged = $temp;
        return $paged;
    }

Это один большой беспорядок, и я думаю, что есть способ сделать его чище с помощью соединений SQL.

Спасибо за помощь!

Обновлять:

Я хочу установить продукты в соответствующей категории/подкатегории/подподкатегории (это функция для основных категорий) в определенном порядке. Это похоже на стек, потому что каждый продукт имеет только свою позицию внутри определенной подкатегории. Подкатегории имеют положение в подкатегориях, подкатегории в категориях.

Так это выглядит так:

категория
- подкатегория 2 (позиция 1)
-- подкатегория 6 (позиция 1)
--- продукт 11 (позиция 1)
--- продукт 7 (позиция 2)
- - подподкатегория 3 (позиция 2) --- товар 3 (позиция 1)
--- товар 2 (позиция 1)

И т.д. Поле "pozycja" - это позиция, а число сразу после элемента - это его id. Итак, теперь мне нужно перебирать элементы, затем устанавливать стек и возвращать только часть.

Имя БД: panelepo_sweb


person Misiur    schedule 24.08.2010    source источник
comment
будет очень полезно, если вы опишете каждую таблицу, используемую в вашем коде, и которую вы пытаетесь достичь.   -  person Michael Pakhantsov    schedule 24.08.2010


Ответы (2)


Да, это большой беспорядок. Было бы полезно, если бы вы немного подчистили и показали нам только те части, которые вызывают проблему.

Обобщить....

$x=SELECT x1 FROM master_table WHERE...
loop
   $y=SELECT y1 FROM next_table WHERE some_foreign_key=$x['x1']....
   loop
      $z=SELECT z1 FROM another_table WHERE some_foreign_key=$y['y1']....

Да, это может быть более эффективным:

$x=SELECT master_table.x1,
      next_table.y1,
      another_table.z1
   FROM master_table, next_table, another_table
   WHERE master_table.x1=next_table.some_foreign_key
   AND next_table.y1=another_table.some_foreign_key
   ORDER BY x1, y1, z1;

Обратите внимание, что порядок требуется только в том случае, если вам нужно сгруппировать записи в зависимости от их иерархии, и вы можете работать с иерархией в одном цикле, сравнивая полученное значение с переменной состояния из предыдущей итерации.

Хотя это экспоненциально уменьшит количество обращений к базе данных и количество синтаксических анализов, необходимых для обработки оператора, это может не привести к значительному снижению общей производительности.

person symcbean    schedule 24.08.2010
comment
Возможно, стоит указать TOP 10 (или эквивалент, если не SQLServer) в SELECT в этой оптимизированной версии запроса и уничтожить всю дискретную логику, которая отфильтровывает все, кроме первых 10 строк... - person Eight-Bit Guru; 24.08.2010
comment
Но это не так :( Ну попробую - person Misiur; 30.08.2010

Я попытался переписать запрос для вас. Попробуйте следующее.

Вы не указали, какую базу данных используете, поэтому некоторый синтаксис (например, TOP) может отличаться.

SELECT top 100 p.id 
FROM subkategorie s
INNER JOIN sub_subkategorie ss on s.id = ss.subkategorie_id
INNER JOIN produkty p on p.id=pr.produkty_id 
INNER JOIN przyporzadkowania pr ss.id = pr.sub_subkategorie_id
INNER JOIN stany_magazynowe st on st.produkty_id = p.id 
INNER JOIN gk_grupy_produkty g on p.id = g.id_produktu 
WHERE s.kategorie_id = '$id'
    AND p.widoczny='1' 
    AND g.id_grupy=$this->int_id_grupy 
    AND g.towar_widocznosc=1 
GROUP BY p.pozycja 
ORDER BY $order    
person D'Arcy Rittich    schedule 24.08.2010