Mysql примеры. Использование механизма транзакций

Детские товары 07.04.2019

В данной статье мы рассмотрим способы обращения к таблицам баз данный MySQL с помощью языка запросов SQL. SQL - это аббревиатура, которая так и "раскрывается" - структуризированный язык запросов.
В языке PHP для это цели существует целый ряд функций с префиксом "mysql". Нам для рассмотрения запросов понадобится не так много из них. Функция, без которой в языке PHP выполнение SQL-запросов было бы просто невозможным:

Resource mysql_query(запрос)

Данная функция посылает запрос к базе данных и возвращает в случае успешного обращения идентификатор ресурса.
Для того чтобы подключиться к базе данных MySQL необходимо выполнить следующую последовательность:

$host="localhost"; // имя хоста (уточняется у провайдера) $database="db_name"; // имя базы данных, которую вы должны создать $user="user_name"; // заданное вами имя пользователя, либо определенное провайдером $pswd="your_pass"; // заданный вами пароль $dbh = mysql_connect($host, $user, $pswd) or die("Не могу соединиться с MySQL."); mysql_select_db($database) or die("Не могу подключиться к базе.");

Итак mysql_connect() - функция для подключения к серверу MySQL на Вашем хостинге.
А mysql_select_db() выбирает базу данных на сервере для подключения.
Иными словами подключаемся к серверу, выбираем базу и начинаем работать.
Функция die() вызывается в случае ошибки и выводит в окно браузера сообщение, которое вы указали.
Для завершения работы с базами данных используется функция:

Mysql_close($dbh);

Здесь $dbh - дескриптор, которые при соединении возвратила функция mysql_connect .
Закончив стартовый обзор, начнем рассмотрение собственно SQL-запросов.
Для этого прежде всего вам необходимо создать базу данных с определенном именем. А в ней создать таблицу, тоже с конкретным именем. В наших примерах будем обращаться к таблице my_sql_table . Чтобы создать эту таблицу давайте выполним в phpmyadmin нашего localhost следующий запрос:

CREATE TABLE `my_sql_table` (`id` INT NOT NULL , // идентификатор будущих записей таблицы `firstname` VARCHAR(50) NOT NULL , // текстовое поле VARCHAR `surname` VARCHAR(50) NOT NULL , // max длиной 50 символов PRIMARY KEY (`id`) // первичный ключ - идентификатор id);

Итак таблица создана. Выполним первый запрос, который сразу оформим в виде PHP-кода:

\n"; echo "Имя: ".$row["firstname"]."
\n"; echo "Фамилия: ".$row["surname"]."


\n"; } ?>

Разберем PHP-код файла firstsql.php . Начнем с собственно запроса к таблицам базы данных (БД).

$query = "SELECT * FROM `my_sql_table`";

Данный запрос можно расшифровать так: выбрать из таблицы my_sql_table БД все записи из всех полей. Таким образом знак * после слова SELECT означает "выбрать абсолютно все". Итак, запрос сформирован. Теперь его надо выполнить:

$res = mysql_query($query);

В случае успешного выполнения запроса функция mysql_query() вернет нам идентификатор ресурса $res .
Его мы должны передать в качестве параметра в функцию mysql_fetch_array() . Название этой функции говорит само за себя. Т.е. она формирует и выдает массив по выборке из таблицы БД. В случае нашей таблицы массив будет состоять из числа элементов, равных количествам записей (строк) в таблице и содержать значения id, firstname, surname для каждой строки таблицы. Следовательно, следующий код:

While($row = mysql_fetch_array($res)) { echo "Номер: ".$row["id"]."
\n"; echo "Имя:".$row["firstname"]."
\n"; echo "Фамилия:".$row["surname"]."


\n"; }

можно прокомментировать так: пока введенная нами переменная $row получает не нулевые результаты работы функции mysql_fetch_row следует выдать в броузер значение полей $row["id"], $row["firstname"], $row["surname"] с помощью echo .
Если запрос выполнить так:

$query = "SELECT firstname FROM `my_sql_table`";

то это будет означать, что из всех строк выбирается только значения поля firstname.
Следовательно предыдущий код следует переписать как:

$res = mysql_query($query); while($row = mysql_fetch_array($res)) { echo "Имя:".$row["firstname"]."
\n"; }

Если Вы хотите выбрать строки таблицы с конкретным значением id где фамилия (surname) будет Петров , то запрос перепишется следующим образом:

$query = "SELECT id FROM `my_sql_table` where surname="Петров"";

А вот если потребуется узнать фамилию того, кто находится под номером, к примеру, 5, то запрос будет таким:

$query = "SELECT surname FROM `my_sql_table` where id=5";

В этом случае Вы знаете, что результатом запроса будет всего одна строка из таблицы. Т.е. нет смысла организовывать цикл с использованием while . И обработка запроса будет следующей

$res = mysql_query($query); $row = mysql_fetch_row($res); echo "Фамилия пятого человека в списке: ".$row."\n";

Здесь вместо mysql_fetch_array() мы применили mysql_fetch_row() . Т.е. получить значение поля (или полей) конкретной строки. Поскольку поле у нас было одно - surname - мы можем обратиться к единственному элементу массива $row как $row; .

Итак, рассмотрим наиболее типичные примеры запросов MySQL. Рассмотрение проведем на базе таблицы my_sql_table :
1. Добавим в таблицу my_sql_table поле middle_name (отчество) после surname :

$query = "ALTER TABLE `my_sql_table` ADD `middle_name`
VARCHAR(50) NOT NULL AFTER `surname`";

2. Теперь удалим поле surname из таблицы my_sql_table:

$query = "ALTER TABLE `my_sql_table` DROP `surname`";

3. Удаляем записи из таблицы my_sql_table с фамилией Сидоров:

$query = "DELETE FROM `my_sql_table` where surname="Сидоров"";

4. Помимо знаков равенства, также "больше" или "меньше", в языке MySQL запросов существует понятие "похоже на ". Выберем записи из таблицы my_sql_table, где в фамилии встречается "дор " :

$query = "SELECT * FROM `my_sql_table` where surname like "%дор%"";

Здесь наличие "% " в начале и конце "дор" и означает, что запрос будет искать именно "дор", причем не важно в начале, конце, или середине фамилии он находится. Рассмотрим следующий пример
5. Выберем записи из таблицы my_sql_table с фамилией, которая начинается на П . Обратите внимание на расположение "% ":

$query = "SELECT * FROM `my_sql_table` where surname like "П%"";

6. Вычислим максимальное значение id :

$query = "SELECT MAX(id) FROM `my_sql_table`";

7. Вычислим количество полей в my_sql_table с фамилией, которая начинается на П .

$query = "SELECT COUNT(*) FROM `my_sql_table` where surname like "П%"";

8. Удаление таблицы my_sql_table:

$query = "DROP TABLE `my_sql_table`";

Для запросов 1-3 на языке PHP достаточно просто выполнить запрос:

Mysql_query($query);

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




Есть еще вопросы или что-то непонятно - добро пожаловать на наш

СУБД MySQL - одна из множества баз данных, поддерживаемых в PHP. Система MySQL распространяется бесплатно и обладает достаточной мощностью для решения реальных задач.

Краткое введение в MySQL

SQL - это аббревиатура от слов Structured Query Language , что означает структурированный язык запросов. Этот язык является стандартным средством для доступа к различным базам данных.

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

Для работы с базами данных удобно пользоваться средством, входящее в комплект Web-разработчика: Denwer phpMyAdmin . Здесь можно создать новую базу данных, создать новую таблицу в выбранной базе данных, заполнить таблицу данными, а также добавлять, удалять и редактировать данные.

В MySQL определены три базовых типа данных: числовой, дата и время и строчный. Каждая из этих категорий подразделяется на множество типов. Основные из них:


Каждый столбец после своего типа данных содержит и другие спецификаторы:

Тип Описание
NOT NULL Все строки таблицы должны иметь значение в этом атрибуте. Если не указано, поле может быть пустым (NULL)
AUTO_INCREMENT Специальная возможность MySQL, которую можно задействовать в числовых столбцах. Если при вставке строк в таблицу оставлять такое поле пустым, MySQL автоматически генерирует уникальное значение идентификатора. Это значение будет на единицу больше максимального значения, уже существующего в столбце. В каждой таблице может быть не больше одного такого поля. Столбцы с AUTO_INCREMENT должны быть проиндексированными
PRIMARY KEY Столбец является первичным ключом для таблицы. Данные в этом столбце должны быть уникальными. MySQL автоматически индексирует этот столбец
UNSIGNED После целочисленного типа означает, что его значение может быть либо положительным, либо нулевым
COMMENT Название столбца таблицы

Создание новой базы данных MySQL CREATE DATABASE .

CREATE DATABASE IF NOT EXISTS `base` DEFAULT CHARACTER SET cp1251 COLLATE cp1251_bin

Создание новой таблицы осуществляется при помощи SQL-команды CREATE TABLE . Например, таблица books для книжного магазина будет содержать пять полей: ISBN, автор, название, цена и количество экземпляров:

CREATE TABLE books (ISBN CHAR(13) NOT NULL, PRIMARY KEY (ISBN), author VARCHAR(30), title VARCHAR(60), price FLOAT(4,2), quantity TINYINT UNSIGNED); Чтобы избежать сообщения об ошибке, если таблица уже есть необходимо изменить первую строчку, добавив фразу "IF NOT EXISTS": CREATE TABLE IF NOT EXISTS books ...

Для создания автообновляемого поля с текущей датой типа TIMESTAMP или DATETIME используйте следующую конструкцию:

CREATE TABLE t1 (ts TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, dt DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP);

Добавление данных в эту таблицу осуществляется при помощи SQL-команды INSERT . Например:

INSERT INTO books (ISBN, author, title, price, quantity) VALUES ("5-8459-0184-7", "Зандстра Мэт", "Освой самостоятельно PHP4 за 24 часа", "129", "5");

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

Символ * означает, что необходимы все поля. Например:

SELECT * FROM books;

Для получения доступа только к некоторому полю следует указать его имя в инструкции SELECT . Например:

SELECT author, title, price FROM books;

Чтобы получить доступ к подмножеству строк в таблице, следует указать критерий выбора, который устанавливает конструкция WHERE . Например, чтобы выбрать имеющиеся в наличии недорогие книги о PHP, надо составить запрос:

SELECT * FROM books WHERE price % Соответствует любому количеству символов, даже нулевых
_ Соответствует ровно одному символу

Для того, чтобы строки, извлеченные по запросу, перечислялись в определенном порядке, используется конструкция ORDER BY . Например:

SELECT * FROM books ORDER BY price;

По умолчанию порядок сортировки идет по возрастанию. Изменить порядок сортировки на обратный можно с помощью ключевого слова DESC :

SELECT * FROM books ORDER BY price DESC;

Сортировать можно и по нескольким столбцам. Вместо названий столбцов можно использовать их порядковые номера:

SELECT * FROM books ORDER BY 4, 2, 3;

Для изменения ранее записанных в таблицу значений нужно воспользоваться командой UPDATE . Например, цену всех книг повысили на 10%:

UPDATE books SET price = price * 1.1;

Конструкция WHERE ограничит работу UPDATE определенным строками. Например:

UPDATE books SET price = price * 1.05 WHERE price

Для удаления строк из базы данных используется оператор DELETE . Ненужные строки указываются при помощи конструкции WHERE . Например, какие-то книги проданы:

DELETE FROM books WHERE quantity = 0;

Если нужно удалить все записи

TRUNCATE TABLE table_name

Для полного удаления таблицы используется:

DROP TABLE table_name

Связь PHP с базой данных MySQL

Поработав с phpMyAdmin над созданием базы данных, можно приступить к подключению этой базы данных к внешнему Web-интерфейсу.

Чтобы получить доступ к базе данных из Web, используя PHP, надо сделать следующие основные шаги:

  • Подключение к серверу MySQL.
  • Выбор базы данных.
  • Выполнение запроса к базе данных:
    • добавление ;
    • удаление ;
    • изменение ;
    • поиск ;
    • сортировка .
  • Получение результата запроса.
  • Отсоединение от базы данных.

Для подключения к серверу базы данных в PHP есть функция mysql_connect() . Ее аргументы: имя компьютера, имя пользователя и пароль. Эти аргументы можно опустить. По умолчанию имя компьютера = localhost , тогда имя пользователя и пароль не требуется. Если PHP используется в сочетании с сервером Apache, то можно воспользоваться функцией mysql_pconnect() . В этом случае соединение с сервером не исчезает после завершения работы программы или вызова функции mysql_close() . Функции mysql_connect() и mysql_pconnect() возвращают идентификатор подключения, если все прошло успешно. Например:

$link = mysql_pconnect (); if (!$link) die ("Невозможно подключение к MySQL");

После того, как соединение с сервером MySQL установлено, нужно выбрать базу данных. Для этого используется функция mysql_select_db() . Ее аргумент: имя базы данных. Функция возвращает true , если указанная база данных существует и доступ к ней возможен. Например:

$db = "sample"; mysql_select_db ($db) or die ("Невозможно открыть $db");

Для добавления, удаления, изменения и выбора данных нужно сконструировать и выполнить запрос SQL. Для этого в языке PHP существует функция mysql_query() . Ее аргумент: строка с запросом. Функция возвращает идентификатор запроса.

Пример 1

Добавление записи в таблицу

При каждом выполнении примера 1 в таблицу будет добавляться новая запись, содержащая одни и те же данные. Разумеется имеет смысл добавлять в базу данные, введенные пользователем.

В примере 2.1 приведена HTML-форма для добавления новых книг в базу данных.

Пример 2.1

HTML-форма добавления новых книг
ISBN
Автор
Название
Цена
Количество

Результаты заполнения этой формы передаются в insert_book.php.

Пример 2.2

Программа добавления новых книг (файл insert_book.php) Пожалуйста, вернитесь назад и закончите ввод"); } $isbn = trim ($_POST["isbn"]); $author = trim ($_POST["author"]); $title = trim ($_POST["title"]) ; $isbn = addslashes ($isbn); $author = addslashes ($author); $title = addslashes ($title) ; $db = "sample"; $link = mysql_connect(); if (!$link) die ("Невозможно подключение к MySQL"); mysql_select_db ($db) or die ("Невозможно открыть $db"); $query = "INSERT INTO books VALUES ("" .$isbn."", "".$author."", "".$title."", "" .floatval($_POST["price"])."", "".intval($_POST["quantity"])."")"; $result = mysql_query ($query); if ($result) echo "Книга добавлена в базу данных."; mysql_close ($link); ?>

В примере 2.2 введенные строковые данные обработаны функцией addslashes() . Эта функция добавляет обратные слеши перед одинарными кавычками ("), двойными кавычками ("), обратным слешем (\) и null-байтом. Дело в том, что по требованиям систаксиса запросов баз данных такие символы дожны заключаться в кавычки.

Для определения количества записей в результате запроса используется функция mysql_num_rows() .

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

В примере 3.1 приведена HTML-форма для поиска определенных книг в базе данных.

Пример 3.1

HTML-форма поиска книг
Ищем по:

Что ищем:

Результаты заполнения этой формы передаются в search_book.php.

Пример 3.2

Пожалуйста, вернитесь назад и закончите ввод"); $searchterm = addslashes ($searchterm); $link = mysql_pconnect (); if (!$link) die ("Невозможно подключение к MySQL"); $db = "sample"; mysql_select_db ($db) or die ("Невозможно открыть $db"); $query = "SELECT * FROM books WHERE " .$_POST["searchtype"]." like "%".$searchterm."%""; $result = mysql_query ($query); $n = mysql_num_rows ($result); for ($i=0; $i<$n; $i++) { $row = mysql_fetch_array($result); echo "

".($i+1). $row["title"]. "



"; } if ($n == 0) echo "Ничего не можем предложить. Извините"; mysql_close ($link); ?>

Альтернативный вариант

Программа поиска книг (файл search_book.php) Пожалуйста, вернитесь назад и закончите ввод"); $searchterm = addslashes ($searchterm); mysql_connect() or die ("Невозможно подключение к MySQL"); mysql_select_db ("sample") or die ("Невозможно открыть БД"); $result = mysql_query ("SELECT * FROM books WHERE ".$_POST["searchtype"]." like "%".$searchterm."%""); $i=1; while($row = mysql_fetch_array($result)) { echo "

".($i++) . $row["title"]."
"; echo "Автор: ".$row["author"]."
"; echo "ISBN: ".$row["ISBN"]."
"; echo "Цена: ".$row["price"]."
"; echo "Количество: ".$row["quantity"]."

"; } if ($i == 1) echo "Ничего не можем предложить. Извините"; mysql_close(); ?>

Итак, как работает архитектура Web-баз данных:

  1. Web-браузер пользователя выдает HTTP-запрос определенной Web-страницы. Например, пользователь, используя HTML-форму, ищет все книги о PHP. Страница обработки формы называется search_book.php.
  2. Web-сервер принимает запрос на search_book.php, извлекает этот файл и передает на обработку механизму PHP.
  3. PHP выполняет соединение с MySQL-сервером и отправляет запрос.
  4. Сервер принимает запрос к базе данных, обрабатывает его и отправляет результат (список книг) обратно механизму PHP.
  5. Механизм PHP завершает выполнение сценария, форматирует результат запроса в HTML. После этого результат в виде HTML возвращается Web-серверу.
  6. Web-сервер пересылает HTML в браузер, и пользователь имеет возможность просмотреть запрошенный список книг.

Использование механизма транзакций

Использование механизма транзакция на примере как передать деньги от одного человека другому

If(mysql_query ("BEGIN") && mysql_query ("UPDATE money SET amt = amt - 6 WHERE name = "Eve"") && mysql_query ("UPDATE money SET amt = amt + 6 WHERE name = "Ida"") && mysql_query ("COMMIT")){ echo "Успешно"; }else{ mysql_query ("ROLLBACK"); echo "Не успешно"; }

SELECT … FOR UPDATE

Если Вы запускаете несколько процессов, которые делают select запрос к одной и той же таблице, то они могут выбрать одну и ту же запись одновременно.

Чтобы избежать вышеупомянутой ситуации необходимо выполнить не просто SELECT запрос, а его расширенную версию, о которой многие и не подозревают: SELECT … FOR UPDATE.

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

Однако не всё так просто. Вам нужно выполнить ещё несколько условий. Во-первых, ваша таблица должна быть создана на основе архитектуры InnoDB. В противном случае блокировка просто не будет срабатывать. Во-вторых, перед выполнением выборки необходимо отключить авто-коммит запроса. Т.е. другими словами автоматическое выполнение запроса. После того как вы укажите UPDATE запрос, необходимо будет ещё раз обратиться к базе и закоммитить изменения с помощью команды COMMIT:

9 октября 2008 в 23:37

Оптимизация MySQL запросов

  • MySQL

В повседневной работе приходится сталкиваться с довольно однотипными ошибками при написании запросов.

В этой статье хотелось бы привести примеры того, как НЕ надо писать запросы.

  • Выборка всех полей
    SELECT * FROM table

    При написании запросов не используйте выборку всех полей - "*". Перечислите только те поля, которые вам действительно нужны. Это сократит количество выбираемых и пересылаемых данных. Кроме этого, не забывайте про покрывающие индексы. Даже если вам на самом деле необходимы все поля в таблице, лучше их перечислить. Во-первых, это повышает читабельность кода. При использовании звездочки невозможно узнать какие поля есть в таблице без заглядывания в нее. Во-вторых, со временем количество столбцов в вашей таблице может изменяться, и если сегодня это пять INT столбцов, то через месяц могут добавиться TEXT и BLOB поля, которые будут замедлять выборку.

  • Запросы в цикле.
    Нужно четко представлять себе, что SQL - язык, оперирующий множествами. Порой программистам, привыкшим думать терминами процедурных языков, трудно перестроить мышление на язык множеств. Это можно сделать довольно просто, взяв на вооружение простое правило - «никогда не выполнять запросы в цикле». Примеры того, как это можно сделать:

    1. Выборки
    $news_ids = get_list("SELECT news_id FROM today_news ");
    while($news_id = get_next($news_ids))
    $news = get_row("SELECT title, body FROM news WHERE news_id = ". $news_id);

    Правило очень простое - чем меньше запросов, тем лучше (хотя из этого, как и из любого правила, есть исключения). Не забывайте про конструкцию IN(). Приведенный код можно написать одним запросом:
    SELECT title, body FROM today_news INNER JOIN news USING(news_id)

    2. Вставки
    $log = parse_log();
    while($record = next($log))
    query("INSERT INTO logs SET value = ". $log["value"]);

    Гораздо более эффективно склеить и выполнить один запрос:
    INSERT INTO logs (value) VALUES (...), (...)

    3. Обновления
    Иногда бывает нужно обновить несколько строк в одной таблице. Если обновляемое значение одинаковое, то все просто:
    UPDATE news SET title="test" WHERE id IN (1, 2, 3).

    Если изменяемое значение для каждой записи разное, то это можно сделать таким запросом:
    UPDATE news SET
    title = CASE
    WHEN news_id = 1 THEN "aa"
    WHEN news_id = 2 THEN "bb" END
    WHERE news_id IN (1, 2)

    Наши тесты показывают, что такой запрос выполняется в 2-3 раза быстрее, чем несколько отдельных запросов.

  • Выполнение операций над проиндексированными полями
    SELECT user_id FROM users WHERE blogs_count * 2 = $value

    В таком запросе индекс использоваться не будет, даже если столбец blogs_count проиндексирован. Для того, чтобы индекс использовался, над проиндексированным полем в запросе не должно выполняться преобразований. Для подобных запросов выносите функции преобразования в другую часть:
    SELECT user_id FROM users WHERE blogs_count = $value / 2;

    Аналогичный пример:
    SELECT user_id FROM users WHERE TO_DAYS(CURRENT_DATE) - TO_DAYS(registered) <= 10;

    Не будет использовать индекс по полю registered, тогда как
    SELECT user_id FROM users WHERE registered >= DATE_SUB(CURRENT_DATE, INTERVAL 10 DAY);
    будет.

  • Выборка строк только для подсчета их количества
    $result = mysql_query(«SELECT * FROM table», $link);
    $num_rows = mysql_num_rows($result);
    Если вам нужно выбрать количество строк, удовлетворяющих определенному условию, используйте запрос SELECT COUNT(*) FROM table, а не выбирайте все строки лишь для того, чтобы подсчитать их количество.
  • Выборка лишних строк
    $result = mysql_query(«SELECT * FROM table1», $link);
    while($row = mysql_fetch_assoc($result) && $i < 20) {

    }
    Если вам нужны только n строк выборки, используйте LIMIT, вместо того, чтобы отбрасывать лишние строки в приложении.
  • Использование ORDER BY RAND()
    SELECT * FROM table ORDER BY RAND() LIMIT 1;

    Если в таблице больше, чем 4-5 тысяч строк, то ORDER BY RAND() будет работать очень медленно. Гораздо более эффективно будет выполнить два запроса:

    Если в таблице auto_increment"ный первичный ключ и нет пропусков:
    $rnd = rand(1, query("SELECT MAX(id) FROM table"));
    $row = query("SELECT * FROM table WHERE id = ".$rnd);

    Либо:
    $cnt = query("SELECT COUNT(*) FROM table");
    $row = query("SELECT * FROM table LIMIT ".$cnt.", 1");
    что, однако, так же может быть медленным при очень большом количестве строк в таблице.

  • Использование большого количества JOIN"ов
    SELECT
    v.video_id
    a.name,
    g.genre
    FROM
    videos AS v
    LEFT JOIN
    link_actors_videos AS la ON la.video_id = v.video_id
    LEFT JOIN
    actors AS a ON a.actor_id = la.actor_id
    LEFT JOIN
    link_genre_video AS lg ON lg.video_id = v.video_id
    LEFT JOIN
    genres AS g ON g.genre_id = lg.genre_id

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

  • Использование LIMIT
    SELECT… FROM table LIMIT $start, $per_page

    Многие думают, что подобный запрос вернет $per_page записей (обычно 10-20) и поэтому сработает быстро. Он и сработает быстро для нескольких первых страниц. Но если количество записей велико, и нужно выполнить запрос SELECT… FROM table LIMIT 1000000, 1000020, то для выполнения такого запроса MySQL сначала выберет 1000020 записей, отбросит первый миллион и вернет 20. Это может быть совсем не быстро. Тривиальных путей решения проблемы нет. Многие просто ограничивают количество доступных страниц разумным числом. Также можно ускорить подобные запросы использованием покрывающих индексов или сторонних решений (например sphinx).

  • Неиспользование ON DUPLICATE KEY UPDATE
    $row = query("SELECT * FROM table WHERE id=1");

    If($row)
    query("UPDATE table SET column = column + 1 WHERE id=1")
    else
    query("INSERT INTO table SET column = 1, id=1");

    Подобную конструкцию можно заменить одним запросом, при условии наличия первичного или уникального ключа по полю id:
    INSERT INTO table SET column = 1, id=1 ON DUPLICATE KEY UPDATE column = column + 1

Читайте


Содержание статьи
1. Самые простые MySQL запросы
2. Простые SELECT (выбрать) запросы
3. Простые INSERT (новая запись) запросы
4. Простые UPDATE (перезаписать, дописать) запросы
5. Простые DELETE (удалить запись) запросы
6. Простые DROP (удалить таблицу) запросы
7. Сложные MySQL запросы
8. MySQL запросы и переменные PHP

1. Самые простые SQL запросы

1. Выведет список ВСЕХ баз.

SHOW databases;
2. Выведет список ВСЕХ таблиц в Базе Данных base_name.

SHOW tables in base_name;

2. Простые SELECT (выбрать) запросы к базе данных MySQL

SELECT – запрос, который выбирает уже существующие данные из БД. Для выбора можно указывать определённые параметры выбора. Например, суть запроса русским языком звучит так - ВЫБРАТЬ такие-то колонки ИЗ такой-то таблицы ГДЕ параметр такой-то колонки равен значению.

1. Выбирает ВСЕ данные в таблице tbl_name.

SELECT * FROM tbl_name;
2. Выведет количество записей в таблице tbl_name.

SELECT count(*) FROM tbl_name;
3. Выбирает (SELECT) из(FROM) таблицы tbl_name лимит (LIMIT) 3 записи, начиная с 2.

SELECT * FROM tbl_name LIMIT 2,3;
4. Выбирает (SELECT) ВСЕ (*) записи из (FROM) таблицы tbl_name и сортирует их (ORDER BY) по полю id по порядку.

SELECT * FROM tbl_name ORDER BY id;
5. Выбирает (SELECT) ВСЕ записи из (FROM) таблицы tbl_name и сортирует их (ORDER BY) по полю id в ОБРАТНОМ порядке.

SELECT * FROM tbl_name ORDER BY id DESC;
6. Выбирает (SELECT ) ВСЕ (*) записи из (FROM ) таблицы users и сортирует их (ORDER BY ) по полю id в порядке возрастания, лимит (LIMIT ) первые 5 записей.

SELECT * FROM users ORDER BY id LIMIT 5;
7. Выбирает все записи из таблицы users , где поле fname соответствует значению Gena .

SELECT * FROM users WHERE fname="Gena";
8. Выбирает все записи из таблицы users , где значение поля fname начинается с Ge .

SELECT * FROM users WHERE fname LIKE "Ge%";
9. Выбирает все записи из таблицы users , где fname заканчивается на na , и упорядочивает записи в порядке возрастания значения id .

SELECT * FROM users WHERE fname LIKE "%na" ORDER BY id;
10. Выбирает все данные из колонок fname , lname из таблице users .

SELECT fname, lname FROM users;

11. Допустим у Вас в таблице пользовательских данных есть страна. Так вот если Вы хотите вывести ТОЛЬКО список встречающихся значений (чтобы, например, Россия не выводилось 20 раз, а только один), то используем DISTINCT. Выведет, из массы повторяющихся значений Россия, Украина, Беларусь. Таким образом, из таблицы users колонки country будут выведены ВСЕ УНИКАЛЬНЫЕ значения

SELECT DISTINCT country FROM users;
12. Выбирает ВСЕ данные строк из таблицы users где age имеет значения 18,19 и 21.

SELECT * FROM users WHERE age IN (18,19,21);
13. Выбирает МАКСИМАЛЬНОЕ значение age в таблице users . То есть если у Вас в таблице самое большее значение age (с англ. возраст) равно 55, то результатом запроса будет 55.

SELECT max(age) FROM users;
14. Выберет данные из таблицы users по полям name и age ГДЕ age принимает самое маленькое значение.

SELECT name, min(age) FROM users;
15. Выберет данные из таблицы users по полю name ГДЕ id НЕ РАВЕН 2.

SELECT name FROM users WHERE id!="2";

3. Простые INSERT (новая запись) запросы

INSERT – запрос, который позволяет ПЕРВОНАЧАЛЬНО вставить запись в БД. То есть создаёт НОВУЮ запись (строчку) в БД.

1. Делает новую запись в таблице users , в поле name вставляет Сергей, а в поле age вставляет 25. Таким образом, в таблицу дописывается новая строки с данными значениями. Если колонок больше, то они оставшиеся останутся либо пустыми, либо с установленными по умолчанию значениями.

INSERT INTO users (name, age) VALUES ("Сергей", "25");

4. Простые UPDATE запросы к базе данных MySQL

UPDATE – запрос, который позволяет ПЕРЕЗАПИСАТЬ значения полей или ДОПИСАТЬ что-то в уже существующей строке в БД. Например, есть готовая строка, но в ней нужно перезаписать параметр возраста, так как он изменился со временем.

1. В таблице users age становится 18.

UPDATE users SET age = "18" WHERE id = "3";
2. Всё то же самое, что и в первом запросе, просто показан синтаксис запроса, где перезаписываются два поля и более.
В таблице users ГДЕ id равно 3 значение поля age становится 18, а country Россия.

UPDATE users SET age = "18", country = "Россия" WHERE id = "3";

5. Простые DELETE (удалить запись) запросы к базе данных MySQL

DELETE – запрос, который удаляет строку из таблицы.

1. Удаляет строку из таблицы users ГДЕ id равен 10.

DELETE FROM users WHERE id = "10";

6. Простые DROP (удалить таблицу) запросы к базе данных MySQL

DROP – запрос, который удаляет таблицу.

1. Удаляет целиком таблицу tbl_name .

DROP TABLE tbl_name;

7. Сложные запросы к базе данных MySQL

Любопытные запросы, которые могут пригодиться даже опытным пользователям

SELECT id,name,country FROM users,admins WHERE TO_DAYS(NOW()) - TO_DAYS(registration_date) <= 14 AND activation != "0" ORDER BY registration_date DESC;
Данный сложный запрос ВЫБИРАЕТ колонки id,name,country В ТАБЛИЦАХ users,admins ГДЕ registration_date (дата) не старше 14 дней И activation НЕ РАВНО 0 , СОРТИРОВАТЬ по registration_date в обратном порядке (новое в начале).

UPDATE users SET age = "18+" WHERE age = (SELECT age FROM users WHERE male = "man");
Выше указан пример так называемого запроса в запросе в SQL. Обновить возраст среди пользователей на 18+, где пол - мужской. Подобные варианты запроса не рекомендую. По личному опыту скажу, лучше создать несколько отдельных - они будут прорабатываться быстрее.

8. Запросы к базе данных MySQL и PHP

В MySQL запросы в PHP странице можно вставлять переменные в качестве сравниваемых и тп значений. Пара примеров

1. Выбирает все записи из таблицы users , где поле fname соответствует значению переменной $name .

SELECT * FROM users WHERE fname="$name";
2. В таблице users ГДЕ id равно 3 значение поля age изменяется на значение переменной $age.

UPDATE users SET age = "$age" WHERE id = "3";

Внимание! Если Вам интересен какой-либо ещё пример, то пишите вопрос в комментарии!

Использование баз данных в значительной степени облегчает человеку жизнь, работу с данными, позволяя получать в краткие сроки нужную информацию из базы, либо записывать в неё. Однако работа с данными требует должного подхода, программисту следует учитывать некоторые аспекты взаимодействия с базами данных. В частности речь идет о MySQL. Далее давайте рассмотрим выжимку из советов по оптимизации взаимодействия с базами данных MySQL.

Делайте запросы MySQL удобными для кэширования

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

// этот запрос MySQL закэшировать не сможет $res = mysql_query("SELECT username FROM user WHERE signup_date >= CURDATE()"); // сделать можно иначе $today = date("Y-m-d"); $res = mysql_query("SELECT username FROM user WHERE signup_date >= "$today"");

Дело в том, что в первом запросе была использована функция CURDATE(), особенность её работы не позволяет помещать результаты запроса в кэш. Значение даты можно предварительно записать в строку запроса, это позволит исключить использование функции CURDATE() в запросе.
По аналогии есть и другие функции, которые не кэшируются самим сервером MySQL, среди них RAND(), NOW() а так же другие функции, результат которых недетерминирован.

Просмотрите как выполняется ваш запрос с помощью синтаксиса EXPLAIN

Посмотреть, как MySQL выполняет ваш запрос можно с помощью синтаксиса EXPLAIN . Его использование может помочь определить слабые места в производительности запроса, а так же в структуре таблиц. В качестве результата запроса EXPLAIN возвратит данные, которые покажут, какие используются индексы, каким образом выбираются данные из таблиц, как сортируются, и т.д. Для этого достаточно добавить вначале SELECT-запроса ключевое слово EXPLAIN, после чего будет показана таблица, с данными.

Когда вам нужна одна запись, выставляйте LIMIT 1

Не мало случаев, когда из таблицы вам требуется проверить наличие хотябы одной записи, в этом случае рекомендуется добавить к запросу параметр LIMIT 1. Это сделает его более оптимальным, т.к. механизм базы данных после нахождения первой записи остановит выборку данных, вместо того чтобы выбирать все данные. Вы экономите ресурсы.

// запрос города с кодом Shymkent из базы $res = mysql_query("SELECT * FROM location WHERE city = "Shymkent""); if (mysql_num_rows($res) > 0){ } // добавляем LIMIT 1 для оптимизации запроса $res = mysql_query("SELECT * FROM location WHERE city = "Shymkent" LIMIT 1"); if (mysql_num_rows($res) > 0){ }

Индексируйте поля по которым производится поиск

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

// тут сработает индекс city LIKE ‘shym%’ // тут же индекс задействован не будет city LIKE ‘%shymkent%’

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

Индексируйте поля по которым объединяются таблицы

Если вы используйте множество объединений таблиц, то вам стоит задуматься о том, чтобы поля, участвующих в объединении были проиндексированы в обеих таблицах. Это дело влияет на то, как MySQL будет производить внутреннюю оптимизацию объединений полей таблицы. Поля объединения должны быть одного типа и одной кодировки. Т.е. к примеру, если одно поле будет иметь тип DECIMAL, а другое INT, то MySQL не сможет воспользоваться индексом.

Найдите альтернативу вместо ORDER BY RAND()

Использование рандомной сортировки действительно является весьма удобным, и об этом такого же мнения многие начинающие программисты. Однако тут есть подводные камни, и очень весомые, используя подобный метод выборки в своих запросах, вы оставляете узкое место в производительности. Здесь же рекомендуется прибегнуть к дополнительному коду вместо использования ORDER BY RAND(), в качестве альтернативы, чтобы избавиться от слабого места в производительности, которое напомнит о себе при увеличении объема данных.

Используйте выборку конкретных полей, вместо SELECT *

Не ленитесь указывать конкретные нужные поля в запросе при выборке, вместо использования «*» — выборка всех полей, дело в том, что чем больше данных считывается из таблицы, тем медленнее становиться ваш запрос.

Добавляйте поле ID для всех таблиц

Каждая таблица в хорошем её исполнении должна иметь поле id типа INT, которое является первичным ключом (PRIMARY_KEY), и AUTO_INCREMENT. Кроме того, для поля нужно указать параметр UNSIGNED, который означает то, что значение всегда будет положительным.
В MySQL есть внутренние операции, которые могут использовать первичный ключ, это играет роль для сложных конфигураций баз данных, таких как кластеры, распараллеливание, и т.д.
Кроме того, если есть несколько таблиц, и необходимо выполнить объединенный запрос, то тут ID таблиц окажется весьма кстати.

ENUM как альтернатива VARCHAR

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

Используйте значение NOT NULL вместо NULL

Поля NULL занимают больше места в записи, из-за того что возникает необходимость отмечать это NULL значение. Таблицы MyISAM, поля с NULL хранятся таким образом, что каждое поле занимает 1 дополнительный бит, который округляется до ближайшего байта. Если использование NULL в поле не принципиально, то рекомендуется использовать NOT NULL.

Пользуйтесь Prepared Statements

$res = "UPDATE hosts SET ip = INET_ATON("{$_SERVER["REMOTE_ADDR"]}") WHERE id = $host_id";

Используйте статичные таблицы

Статичная таблица это обычная таблица в базе, за исключеним того, что каждое поле в таблице имеет фиксированный размер. Если в таблице есть колонки, не фиксированной длины, к примеру, это могут быть: VARCHAR, TEXT, BLOB, она перестает быть статичной, и будет обрабатываться MySQL немного иначе. Статичные таблицы, или их можно ещё назвать таблицами фиксированного размера работают быстрее не статичных. Записи из таких таблицах будут просматриваться быстрее, при необходимости выбора нужной строки MySQL быстро вычислит её позицию. Если поле имеет не фиксированный размер, то в этом случае поиск производиться по индексу. Есть и другие плюсы использования статических таблиц, дело в том, что эти таблицы проще кэшируются, а так же восстанавливаются после падения базы данных.

Используйте вертикальное разделение

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

Разделяйте объемные запросы INSERT и DELETE

Выполнение большого объема запросов такого рода может привести к блокировке таблицы, вследствие чего, к неправильной работы приложения в целом. Параллельные запросы на веб-сервер могут порождать дополнительное обращение к таблице. Если таблица заблокирована предыдущим запросом, последующие запросы выстраиваются в очередь, и как следствие это проявляется в виде торможения сайта, а то и падения сервера.
Если вам необходимо сделать множество запросов, постарайтесь контролировать их, отдавая небольшими сериями, а не скидывать всё на базу данных. При этом возможно ваш запрос будет выполняться дольше, но это менее скажется на других пользователях.
Пример:

While (1){ mysql_query("DELETE FROM logs WHERE log_date <= "2015-07-20" LIMIT 1000"); if (mysql_affected_rows() == 0){ // записи удалены успешно break; } usleep(50000); // делаем небольшую паузу }

Стремитесь использовать поля небольшого размера

Как известно данные базы хранятся на жестком диске, это зачастую это может оказаться одним из слабых мест в веб-приложении. Дело в том, что записи небольшого размера являются более предпочтительными, т.к. использование их уменьшает работу с жестким диском. Если вы уверенны, что конкретная таблица будет хранить мало строк, то рациональным решением будет использование типов полей, с минимальными возможными значениями. К примеру, если основной ключ имеет тип INT, и вы будете хранить в таблице лишь небольшое кол-во данных, то лучше сделать его типа MEDIUMINT, SMALLINT или даже TINYINT.

Выбирайте тип таблиц под свои задачи

Два широко известных типа таблиц на сегодняшний день, это MyISAM и InnoDB , каждый из них имеет свои положительные и отрицательные стороны. К примеру, MyISAM хорошо считывает данные из таблиц в большом объеме, одно он более медлителен при записи. Он так же хорошо выполняет запросы вида SELECT COUNT(*).
Механизм хранения данных у InnoDB более сложный, чем у MyISAM, однако, он поддерживает блокировку строк, что является положительной стороной при масштабировании. Поэтому сказать, что одно лучше другого нельзя, да и не правильно, нужно выбирать тип исходя из своих потребностей.



Рекомендуем почитать

Наверх