Эффективный массив PHP и выберите

Я могу решить эту проблему с помощью нескольких операторов foreach, но загрузка страницы занимает целую вечность, когда в каждом классе 26 учеников, а у некоторых предметов до 13 ’radnummer’. См. Примеры ниже.

Это то, что я предпочитаю выводить (строки и столбцы): Эффективный массив PHP и выберите

Проблема: загружается вечно.

Вопрос: как мне его ускорить и сделать более эффективным?

Таблица первая, в которой я выбираю всех учеников в классе (ВЫБРАТЬ 1):

SELECT `intressenter_alla`.id, `intressenter_alla`.fornamn, `intressenter_alla`.efternamn
FROM `intressenter_alla` 
INNER JOIN `klass_elev` 
ON `intressenter_alla`.id = `klass_elev`.id
WHERE (`klass_elev`.klass = :klassen)
ORDER BY `intressenter_alla`.efternamn, `intressenter_alla`.fornamn ASC

PRINT_R дает:

Array ( 

      [0] => Array ( 
      [id] => 1226 
      [0] => 1226 
      [lid] => 0 
      [1] => 0 
      [fornamn] => Peter
      [2] => Peter 
      [efternamn] => Strobe 
      [3] => Strobe 
      [personnr] => 070920-8690 
      [4] => 070920-8690 
      [mejl] => [email protected]  
      [5] => [email protected]  
      [6] => 1226 
      [klass] => 6B 
      [7] => 6B
)

      [1] => Array ( 
      [id] => 1227 
      [0] => 1227 
      [lid] => 0 
      [1] => 0 
      [fornamn] => Victor 
      [2] => Victor 
      [efternamn] =>Gand 
      [3] => Gand 
      [personnr] => 070518-8995 
      [4] => 070518-8995
      [mejl] => [email protected] 
      [5] => [email protected]
      [6] => 1227 
      [klass] => 6B 
      [7] => 6B
)
)

Таблица 2, где я выбираю соответствующие данные для каждого студента. Вот тут проблема. В этом примере у каждого студента должно быть пять строк 'radnummer' (см. Ниже) для этого конкретного предмета. Появляется только последний. В каждой строке должно отображаться определенное значение kunsk_klick. См. Пример ниже (ВЫБРАТЬ 2):

SELECT * 
FROM `iup_kunskapskrav_klick` 
WHERE elev_id = ? AND radnummer = ? AND amne_id = ? AND arskurs = ?
ORDER BY radnummer, datum DESC

PRINT_R дает:

Array ( 
   [kunsk_id] => 138557
   [0] => 138557 
   [amne_id] => 1 
   [1] => 1 
   [radnummer] => 5 
   [2] => 5 
   [elev_id] => 1226 
   [3] => 1226 
   [arskurs] => 5 
   [4] => 5 
   [lid] => 1 
   [5] => 1 
   [kunsk_klick] => E 
   [6] => E 
   [datum] => 2018-05-29 
   [7] => 2018-05-29 
) 

Array ( 

   [kunsk_id] => 138561 
   [0] => 138561 
   [amne_id] => 1 
   [1] => 1 
   [radnummer] => 5 
   [2] => 5 
   [elev_id] => 1227 
   [3] => 1227 
   [arskurs] => 5 
   [4] => 5 
   [lid] => 1 
   [5] => 1 
   [kunsk_klick] => E 
   [6] => E 
   [datum] => 2018-05-29 
   [7] => 2018-05-29 
)

РЕДАКТИРОВАТЬ 1: структура таблиц.

Стол intressenter_alla

CREATE TABLE `intressenter_alla` (
  `id` int(4) NOT NULL,
  `lid` int(3) NOT NULL,
  `fornamn` varchar(255) NOT NULL,
  `efternamn` varchar(255) NOT NULL,
  `personnr` varchar(12) NOT NULL,
  `mejl` varchar(255) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Стол iup_kunskapskrav_klick

CREATE TABLE `iup_kunskapskrav_klick` (
  `kunsk_id` int(11) UNSIGNED NOT NULL,
  `amne_id` int(3) NOT NULL,
  `radnummer` int(10) NOT NULL,
  `elev_id` int(3) NOT NULL,
  `arskurs` int(2) NOT NULL,
  `lid` int(3) NOT NULL,
  `kunsk_klick` varchar(3) COLLATE utf8_swedish_ci NOT NULL,
  `datum` date NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_swedish_ci;

Стол klass_elev

CREATE TABLE `klass_elev` (
  `id` int(5) NOT NULL,
  `klass` varchar(2) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COMMENT='Elevid och klass.';

Обновлено еще раз: пример кода (я знаю, плохое смешивание PHP и HTML, а также плохие отступы ...).

<?php

// All students (See SELECT number 1)
$hamta_hela_klassen = $anvandare->klasslista($_GET['klass']);

// Count how many radnummer there is in the subject
$count = 0;
$count = $abb->rakna_kunskapskrav($_GET['amne_id'], $arskursens);

echo "<table>";
echo "<thead>";
echo "<tr><th>Nr.</th><th>Picture</th><th>Name</th>";
if ($count<=1){
    echo "<th scope='row' style='vertical-align:middle;text-align:center'>Kunskapskrav</th>";
} else {
    for($i=1;$i<=$count;$i++)
    {
        // This outputs R1 - R2 and so on in the header of the columns (see the picture above)
        echo "<th width='1%' scope='row' style='vertical-align:middle;text-align:center'>R".$i."</th>";
    }
}

echo "<th>Date</th><th>Button</th>";

$raknare = 0;

// Loop out each student. Not the most effective way...                                                               
foreach ($hamta_hela_klassen as $klassuppgifter){
    $raknare++;

    // Profile picture
    $profilbild = '/home/jo/public_html/no/students/profilbilder/'.$klassuppgifter['id'].'.jpg';

    echo "<td>";
    echo AKTIV_URL."students/profilbilder/".$klassuppgifter['id'].".jpg";
    echo "</td>";

    // NAME
    echo "<td>";
    echo $klassuppgifter['fornamn']." ".$klassuppgifter['efternamn'];
    echo "</td>";

    if ($count<=1){
        echo "<td>Empty.</td>";
    } else {for($i=1;$i<=$count;$i++)
    {

        // Fetching each corresponding RADNUMMER for each student (see SELECT 2 above)                                      

        $iup_info_k1 = $iup->hamta_ett_kunskapskrav_klick_klass($klassuppgifter['id'], $i,$_GET['amne_id'], $arskursen);

        if (empty($iup_info_k1) && ($arskursen == '5' || $arskursen =='6' || $arskursen =='8' || $arskursen =='9')){
            $arskursen_lager = $arskursen -1;
            $iup_info = $iup->hamta_ett_kunskapskrav_klick_klass($klassuppgifter['id'], $i,$_GET['amne_id'], $arskursen_lager);
        } else {
            $iup_info = $iup_info_k1;
        }

        //Special for students in 4 - 5
        if ($arskursen=='4' || $arskursen=='5') {
            if ($iup_info['kunsk_klick'] == "G"){$betyget = 'P';}
            if ($iup_info['kunsk_klick'] == "F"){$betyget = 'O';}
            elseif ($iup_info['kunsk_klick'] == "E"){$betyget = '1';}
            elseif ($iup_info['kunsk_klick'] == "C"){$betyget = '2';}
            elseif ($iup_info['kunsk_klick'] == "A"){$betyget = '3';}
            elseif (empty($iup_info['kunsk_klick'])) {$betyget = "P"; }
        }

        //Special for students in 6 - 9
        if ($arskursen=='6' || $arskursen=='7' || $arskursen=='8' || $arskursen=='9') {
            if ($iup_info['kunsk_klick'] == "G"){$betyget = 'P';}
            elseif (empty($iup_info['kunsk_klick'])) {$betyget = "P"; }
            else { $betyget = $iup_info['kunsk_klick']; }
        }
        echo "<td>".$betyget."</td>";
    }
    }

    // DATE
    echo "<td>";
    echo $iup_info['datum'];
    echo "</td>";

    // Edit button
    echo "<td>";
    echo "EDIT";
    echo "</td>";


}

echo "</tr>";

echo "</tbody>";
echo "</table>";

?>

Изменить 3:

Чтобы ТОЛЬКО выводил данные столбца названный, а не числовые данные, я меняю оператор выборки:

$ pdo-> fetchAll (PDO :: FETCH_ASSOC);

Теперь это выглядит так:

    Array ( 
       [kunsk_id] => 138561 
       [amne_id] => 1 
       [radnummer] => 5 
       [elev_id] => 1227 
       [arskurs] => 5 
       [lid] => 1 
       [kunsk_klick] => E 
       [datum] => 2018-05-29 
    )

Можете ли вы показать нам свой реальный код (а не только запросы)? Я предполагаю, что есть запросы в циклах? Кроме того, удостоверились ли вы, что ваши таблицы правильно проиндексированы? Уже одно это ускорит ваши запросы много.

Magnus Eriksson 08.08.2018 10:51

Очень сложно следить за вопросом, не зная схемы базы данных. Не могли бы вы реплицировать базу данных, например, в SQL Fiddle (sqlfiddle.com)?

drodil 08.08.2018 10:54

... или еще лучше, добавьте схему здесь, на SO (чтобы будущие посетители также могли ее видеть).

Magnus Eriksson 08.08.2018 10:55

@MagnusEriksson фактический код довольно обширен. Можно ли показать его части? Пока спасибо.

Per76 08.08.2018 11:11

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

Magnus Eriksson 08.08.2018 11:45

@MagnusEriksson благодарит вас за вашу помощь. Я обновил вопрос. См. Редактирование 2.

Per76 08.08.2018 12:12

1) эээ, похоже, ни одна из ваших таблиц схемы MySQL не имеет индексов ...

Martin 08.08.2018 12:14

@Martin Спасибо! Сделано много, чтобы добавить индекс по elev_id в одну из таблиц. Я чувствую себя NOOB. Хорошего дня!

Per76 08.08.2018 12:27

@ Per76, пожалуйста, посмотрите мой ответ ниже.

Martin 08.08.2018 12:49
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
9
97
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Судя по ответу Per76, этот комментарий представляется эффективным решением:

None of your MySQL Schema tables seem to have indexes.

Итак ... добавьте индексы в свои таблицы SQL. В идеале вам следует проиндексировать все столбцы, на которые вы ссылаетесь в любом предложении WHERE, любом предложении JOIN или любом ORDER BY. Индексирование - ключ к быстродействию MySQL.

Повышение производительности запросов за счет индексации столбцов в MySQL

Как работают индексы MySQL?

Как добавить индексы в таблицы MySQL?


ПРИМЕЧАНИЕ: Перечисленные здесь предложения - микрооптимизация и будут иметь лишь минимальное влияние на время загрузки страницы и / или эффективность. Это настройки Только, и их улучшения будут бледными по сравнению с улучшениями, полученными от реализации правильной индексации столбцов в MySQL, как указано выше.

  • Использование PHP-операторов switch вместо повторяющихся elseif.

        if ($iup_info['kunsk_klick'] == "F"){$betyget = 'O';}
        elseif ($iup_info['kunsk_klick'] == "E"){$betyget = '1';}
        elseif ($iup_info['kunsk_klick'] == "C"){$betyget = '2';}
        elseif ($iup_info['kunsk_klick'] == "A"){$betyget = '3';}
        elseif (empty($iup_info['kunsk_klick'])) {$betyget = "P"; }
    

    становится

        switch($iup_info['kunsk_klick']) {
             case "F":
                 $betyget = 'O';
                 break;
             case "E":
                 $betyget = '1';
                 break;
             case "C":
                 $betyget = '2';
                 break;
             case "A":
                 $betyget = '3';
                 break;
             case "":
                 $betyget = 'P';
                 break;
        }
    
  • Используйте правильный MySQL Целочисленный тип для определений столбцов. Многие из ваших столбцов INT с длиной всего 3, 4 или 5 столбцов могут быть UNSIGNED SMALLINT.

  • Унификация типов данных столбцов MySQL, чтобы столбцы INT(4) сравнивались с другими столбцами INT(4) в предложениях JOIN и WHERE.
  • Используйте наборы символов и сопоставления utf8mb4 вместо дрянного 3-байтового UTF-8 (Хм? Wtf?)
  • Эффективность приведения типов в операторах if: (int)$arskursen===6 быстрее и эффективнее (за небольшую отметку), чем $arskursen=='6'
  • Исправьте свой PHP, чтобы ТОЛЬКО выводил данные столбца названный, а не также данные числовых индикаторов (вы играете с вдвое большим количеством данных, чем необходимо в PHP). Пример:

    Array ( 
       [kunsk_id] => 138561 
       [amne_id] => 1 
       [radnummer] => 5 
       [elev_id] => 1227 
       [arskurs] => 5 
       [lid] => 1 
       [kunsk_klick] => E 
       [datum] => 2018-05-29 
    )
    

Просто из любопытства, есть ли какие-либо ссылки на «повышение эффективности» (которое вы упомянули в комментарии под OP) при использовании switch/case вместо if/else? В этом случае (без каламбура) использование switch/case действительно делает код более читаемым, но все, что я читал по этому поводу, в основном заканчивается выводом об отсутствии реальной разницы в производительности.

Magnus Eriksson 08.08.2018 13:13

@MagnusEriksson switch только один раз считывает значение переменной и проверяет его на соответствие каждому дело. В руководстве указано: «В операторе switch условие оценивается только один раз, а результат сравнивается с каждым оператором case. В операторе elseif условие оценивается снова». Следовательно, переключение было бы немного более эффективным. Но я должен заявить, что все мои замечания, кроме индекса MySQL, будут лишь небольшими улучшениями. :-)

Martin 08.08.2018 13:33

Конечно, но я серьезно сомневаюсь, что простое чтение переменной один или 50 раз вообще изменит какую-либо (заметную) разницу. Похоже на мать всех микрооптимизаций. :-) Это немного другое, если вы можете использовать функцию для каждого из них. Тогда может быть существенная разница.

Magnus Eriksson 08.08.2018 13:35

@MagnusEriksson да, я могу с этим согласиться; поскольку на самом деле чтение мануальной записи на switch означает, что это только улучшение значительный сложных сравнений, а не простых сравнений. Но у меня есть привычка предпочитать switch блоку elseif''\_(;-)_/''.

Martin 08.08.2018 13:38

Ничего плохого в этом нет. Во всяком случае, это часто делает код более читабельным. Я просто боюсь, что упоминание этого в ответе о производительности может привести к новому буйству типа «двойные кавычки против одинарных кавычек». Если не используется сложное выражение, то есть. В PHP так много вещей, которые люди все еще применяют, и рекомендуют использовать для заметных различий в некоторых ситуациях, но в основном это проблемы сегодня :-p

Magnus Eriksson 08.08.2018 13:42

@MagnusEriksson Я добавил квалификатор (дис) к своему ответу выше

Martin 08.08.2018 13:56

@Martin Спасибо! Очень любезно с вашей стороны ответить и дать действительно хорошие советы. Один (новичок) вопрос: как мне лучше всего вывести данные именованного столбца? Или, может быть: как мне не получать и данные числовых индексов?

Per76 08.08.2018 16:27

@ Per76 используйте что-то вроде этого: php.net/manual/en/mysqli-result.fetch-assoc.php

Martin 08.08.2018 16:31

Режим выборки по умолчанию - FETCH_BOTH. Я изменил свой режим на FETCH_ASSOC, чтобы получать только нечисловые клавиши. $ pdo-> fetchAll (PDO :: FETCH_ASSOC);

Per76 08.08.2018 17:02

@ Per76 да, должно работать именно так, как вам нужно. :-)

Martin 08.08.2018 17:03

Другие вопросы по теме