БлогNot. PHP: ответ при наведении, база в 130000 вопросов и Как Выполнить Большой Запрос

PHP: ответ при наведении, база в 130000 вопросов и Как Выполнить Большой Запрос

Показанный ниже небольшой сервис напоминает разного рода "Фразы дня" и "Случайные анекдоты", часто попадающиеся на популярных ресурсах. Случайная строка представляет собой вопрос вроде тех, что распространены в онлайн-викторинах, а ответ появляется при наведении курсора мыши на вопрос (то есть, он "зашит" в HTML-атрибут title вопроса). Строка с вопросом выбирается из базы данных MySQL, при большом количестве записей это несравнимо лучше, чем использовать текстовые файлы. Для простоты генерация выполняется за 2 запроса - первый узнаёт общее количество записей, второй выбирает случайную запись.

Проверил на базе примерно в 150000 записей - никакого "торможения" не заметил (база показанного ниже "примера в работе" - всего 100 записей, нечего место на хостинге занимать :)

Вот полный исходник класса сервиса и пример его вызова:

<!DOCTYPE html>
<html lang="ru">
<head>
 <META HTTP-EQUIV="Pragma" CONTENT="no-cache">
 <meta charset="utf-8">
 <title>Title Tool Tip</title>
</head>
<body bgcolor="#EEEEEE" text="#111111">
<?php
 class TitleToolTipSelector {
  private $DB_HOST, $DB_LOGIN, $DB_PASS, $DB_NAME, $DB_TABLE, $DB_CODEPAGE;

  public function __construct ($DB_HOST='localhost', $DB_LOGIN='root', $DB_PASS='root',
   $DB_NAME='test', $DB_TABLE='data', $DB_CODEPAGE='utf8') {
   $this->DB_HOST = $DB_HOST;
   $this->DB_LOGIN = $DB_LOGIN;
   $this->DB_PASS = $DB_PASS;
   $this->DB_NAME = $DB_NAME;
   $this->DB_TABLE = $DB_TABLE;
   $this->DB_CODEPAGE = $DB_CODEPAGE;
   $this->conid=0;
   $this->get_conid();
  }
  public function __destruct () {
   mysqli_close($this->get_conid());
  }
  private function get_conid () {
   static $conid=0;
   if ($conid===0) {
    $conid=mysqli_connect ($this->DB_HOST, $this->DB_LOGIN, $this->DB_PASS);
    if ($conid!==false) {
     mysqli_select_db ($conid, $this->DB_NAME);
     mysqli_set_charset ($conid, $this->DB_CODEPAGE);
    }
   }
   return $conid;
  }
  public function show () {
   $count=mysqli_fetch_array(mysqli_query($this->get_conid(),'select count(q) from '.$this->DB_TABLE));
   $number= rand(0,$count[0]-1);
   $data=mysqli_fetch_assoc(mysqli_query($this->get_conid(),'select q,a from '.$this->DB_TABLE.' limit '.$number.',1'));
   echo '<div align="center"><span title="'.$data['a'].'">'.$data['q'].'</span>
    <br><font size=-1>(поднесите курсор к вопросу и узнаете ответ)</font></div>';
  }
 }
 
 $t=new TitleToolTipSelector(); 
 $t->show(); //Пример вызова класса
 echo '<div align="center"><a href="'.$_SERVER['PHP_SELF'].'">ещё...</a></div>'; //Просто для удобства - ссылка "Обновить"
 echo '<div align="center"><a href="http://blog.kislenko.net/show.php?id=986">что за скрипт?</a></div>';
?>
</body></html>

 Скрипт в работе онлайн (всего 100 записей)

На реальном хостинге просто вызовите конструктор класса new TitleToolTipSelector() с нужными параметрами (имя_хоста, логин_к_SQL, пароль_к_SQL, имя_базы, имя_таблицы, кодировка), в примере я вызвал его без параметров, потому что все их значения приняты на локалхосте по умолчанию.

Структура таблицы, требуемой скрипту, самая простая, вот запрос, создающий базу test и таблицу data "с нуля" (на реальном хостинге может понадобиться только последний оператор MySQL):

DROP DATABASE IF EXISTS test;
CREATE DATABASE test;
USE test;
DROP TABLE IF EXISTS data;
CREATE TABLE data (
 q varchar(512),
 a varchar(64)
);

Наконец, самым полезным в этой заметке может оказаться база вопросов и ответов в формате MySQL, более 130000 записей, структура запроса соответствует показанной выше структуре БД.

 Скачать базу данных SQL вопросов и ответов в архиве ZIP с Яндекс.Диска (~3.3 Мб)

Импортировать это можно стандартными средствами - выбрать в phpMyAdmin базу, потом Импорт, кодировка файла utf-8 (Юникод), формат SQL. Предполагается, что база называется test, а таблица - data, если это не так, замените в первой строке распакованного файла название базы, и во всём файле - строку INSERT INTO data на INSERT INTO ВАШЕ_ИМЯ_ТАБЛИЦЫ.

Для удобства данные добавляются "порциями" по 10000 записей в одном запросе. Тем не менее, если в Вашей системе такие большие запросы не выполняются, например, соединение завершается с "загадочной ошибкой" #2006 - MySQL server has gone away, помочь может рецепт, который я применил у себя на локалхосте:

Находим файл конфигурации MySQL, у него имя my.ini, а находится он в рабочей папке службы, у меня это была C:\Program Files\MySQL\MySQL Server 5.5\

Открываем любым текстовым редактором, находим в файле секцию

[mysqld]

и в ней добавляем запись

max_allowed_packet = 64M

(или ставим новую, если переменной max_allowed_packet вообще не было).

После этого в Windows идём Администрирование - Службы, остановить и снова запустить службу MySQL.

После импортирования лучше закомментировать добавленное значение max_allowed_packet (первым символом # в строке) и снова перезапустить службу, чтобы зря память не жрала :)

P.S. Начиная с версии PHP 5.5 следует поменять код, работающий с MySQL, на код с MySQLi, это нетрудно (уже сделано в показанном выше листинге).

23.05.2013, 22:10 [12403 просмотра]


теги: php random сервис mysql

К этой статье пока нет комментариев, Ваш будет первым