2016-12-18 4 views
0

У меня возникла проблема с простым запросом к моей базе данных MySQL с использованием библиотек CodeIgniter3. Я столкнулся с проблемами, обнаружившими узкое место и хотел бы услышать ваши мнения.CodeIgniter3 и results_array() time-out

Технические характеристики:

  • РНР 5.4
  • CodeIgniter 3.1.2
  • MySQL 5.1.73 (через /var/lib/mysql.sock)

Таблица 'Уведомления':

+-------------+--------------+------+-----+------------+----------------+ 
| Field  | Type   | Null | Key | Default | Extra   | 
+-------------+--------------+------+-----+------------+----------------+ 
| id   | int(11)  | NO | PRI | NULL  | auto_increment | 
| receiver_id | int(11)  | NO | MUL | 0   |    | 
| content  | varchar(254) | NO |  | NULL  |    | 
| created  | varchar(10) | NO |  | 1000000000 |    | 
| seen  | set('0','1') | NO |  | 0   |    | 
+-------------+--------------+------+-----+------------+----------------+ 
5 rows in set (0.01 sec) 

Прямой запрос внутри MySQL:

mysql> select * from notifications order by created desc limit 100; 
... 
... 
100 rows in set (0.01 sec) 

Запрос с CodeIgniter:

// Load User's Notifications 
public function LoadNotifications($UserID) 
{ 
    // Load Replies 
    $sql   = "SELECT id, content, created, seen FROM notifications WHERE receiver_id=$UserID ORDER BY created DESC LIMIT 100"; 
    $query   = $this->db->query($sql); 
    if($query->num_rows() == 0) return '0'; 
    $results  = $query->result_array(); 
    return $results; 
} 

Мои наблюдения и долгое время пытаются найти причину, выяснилось, что эта линия причины проблема:

$results  = $query->result_array(); 

CodeIgniter предлагает другой способ, чтобы получить результаты в виде объекта, который с помощью этой команды вместо:

$results  = $query->result(); 

Как вы уже догадались, я получаю тот же результат с PHP съедает все CPU и Nginx время соединения вне с HTTP/1,1 504

  • Я попытался войти Mysql_Slow_Queries, ни один не было найдено.
  • Таблица используется для хранения InnoDB двигатель (ключ использование буфера ~ 98%)

PHP CPU Usage on CodeIgniter Query

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

Заранее спасибо

+0

Вы используете '$ this-> output-> enable_profiler (true)'? – Dan

+0

Нет, я нет. Я предоставил код точно так же, как он используется в приложении. Если необходимо, укажите, почему, и почему запрос без профилировщика вызывает такие проблемы. Спасибо –

+1

Можете ли вы просто использовать запрос 'SELECT id, content, created, seen FROM notification LIMIT 10' и посмотреть, есть ли у вас проблема? Если нет, это означает, что проблема фильтрации может быть проблемой. Попробуйте 'SELECT id, content, created, seen FROM FROM ORDER BY created DESC LIMIT 10'. Если это выглядит хорошо, заказ хорош. Фильтрация может быть проблемой. Попробуйте 'SELECT id, content, created, seen FROM FROM WHERE receiver_id = 1 ORDER BY created DESC LIMIT 10'. Если это нормально, попробуйте выполнить '$ UserID = sprintf ("% d ", $ UserID);' перед '$ sql ...' для преобразования вашего UserID в int. – zedfoxus

ответ

0

Ответ

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

После function LoadNotifications($UserID) возвращают результаты, и в то время как CodeIgniter фактически отдавая $results возвращаемым массив, я имел яваскрипт строку:

foreach($results as $notification) 
{ 
    echo $notification["content"] . "<br />"; 
    echo "<script> some JS code </script>"; 
} 

Проблема была вызвана моей используемой рядным Javascript библиотекой запутывания CI_Minifier который вызвало 100 экземпляров обфускации, которые будут запущены одновременно, чтобы обмануть те 100 <script> строк, которые у меня были внутри цикла.

Нижняя линия:

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

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

Спасибо @zedfoxus и @Dan за ваши попытки помочь мне.

0

Для первого запроса вам нужен указатель на created. Вероятно, вам нужно превратить эту колонку в числовой тип данных, а не VARCHAR.

Для второго запроса вам нужен другой индекс, составной INDEX(receiver_id, created). Ваш текущий INDEX(receiver_id) не так хорош. Поскольку это префикс той, которую я рекомендую, я рекомендую вам удалить вашу.

+0

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

+0

«время ожидания» и «съедание всего процессора» привкус «исполнения». 'result *' ждет, когда база данных завершит сбор всего результирующего набора. –

+0

не очень, см. Мой ответ ниже. Я был «in-line», запутывающий JS, сгенерированный с результатом, который выпустил сотни экземпляров встроенного модуля обфускации. «$ Result» возвращается в 0,01 секунды независимо от того, как marge, это не проблема с БД, спасибо. –

Смежные вопросы