Тарифы Услуги Сим-карты

Примеры SQL запросов к базе данных MySQL. Оптимизация MySQL запросов

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

СУБД MySQL - что это?

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

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

Как должно быть организовано хранение данных

Для удобного хранения и последующей обработки данные обязательно упорядочиваются. Структура данных позволяет определить, каким образом будут выглядеть таблицы, использующиеся для хранения информации. Таблицы базы данных представляют собой набор полей (столбцов), отвечающих за каждое определенное свойство объекта данных.

Например, если составляется таблица сотрудников определенной компании, то ее самая простая структура будет иметь следующий вид. За каждым сотрудником закреплен уникальный номер, который, как правило, используется в качестве первичного ключа к таблице. Затем в таблицу заносятся персональные данные сотрудника. Это может быть что угодно: Ф. И. О., номер отдела, за которым он закреплен, телефон, адрес и прочее. Согласно требованиям нормализации (6 нормальных форм баз данных), а также для того, чтобы MySQL-запросы выстраивались структурированно, поля таблицы должны быть атомарными, то есть не иметь перечислений или списков. Поэтому, как правило, в таблице существуют отдельные поля для фамилии, имени и т. д.

Иванович

Администрац.

Директор

Петрович

Администрац.

Зам. директора

Григорий

Григорьевич

Начальник

Сергеевич

Продавец-консульт.

Выше представлен тривиальный пример структуры таблицы базы данных. Однако она ещё не до конца отвечает основным требованиям нормализации. В реальных системах создается дополнительная таблица отделов. Поэтому приведенная таблица вместо слов в колонке «Отдел» должна содержать номера отделов.

Каким образом происходит выборка данных

Для получения данных из таблиц в СУБД используется специальная команда MySQL - запрос Select . Для того чтобы сервер правильно отреагировал на обращение, запрос должен быть корректно сформирован. Структура запроса формируется следующим образом. Любое обращение к серверу БД начинается с ключевого слова select . Именно с негостроятся все вMySQL запросы. Примеры могут иметь различную сложность, но принцип построения очень похож.

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

Для ограничения выборки в MySQL-запросы добавляются специальные операторы, предусмотренные СУБД. Для выборки неповторяющихся (уникальных) данных используется предложение distinct , а для задания условий - оператор where . В качестве примера, применимого к вышеуказанной таблице, можно рассмотреть запрос, требующий информацию о Ф.И.О. сотрудников, работающих в отделе «Продажи». Структура запроса примет вид, как в таблице ниже.

Понятие вложенного запроса

Но главная особенность СУБД, как было указано выше, возможность обрабатывать вложенные запросы MySQL. Как он должен выглядеть? Из названия логически понятно, что , сформированный в определенной иерархии из двух или более запросов. В теории по изучению особенностей СУБД сказано, что MySQL не накладывает ограничений на количество MySQL-запросов, которые могут быть вложены в главный запрос. Однако можно поэкспериментировать на практике и убедиться, что уже после второго десятка вложенных запросов время отклика серьезно увеличится. В любом случае на практике не встречаются задачи, требующие использовать чрезвычайно сложный MySQL-запрос. В запросе может потребоваться максимально до 3-5 вложенных иерархий.

Построение вложенных запросов

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

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

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

Итоги

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

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

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

Теперь переходим к отправке запросов к базе данных в PHP :


}
$mysqli->query("INSERT INTO mytable (name, email) VALUES ("MyName", "[email protected]")");
$mysqli->close();
?>

В данном примере мы подключились к базе данных, проверили успешность подключения, отправили запрос с помощью метода query() , а затем закрыли подключение. Как видите, всё очень просто. Для отправки любых SQL-запросов достаточно всего одного метода - query() , поэтому в данном случае всё безумно просто.

Теперь чуть-чуть усложним задачу. Давайте с Вами разберём запросы, которые возвращают result_set - результат. Самый популярный запрос, возврающающий result_set - это выборка данных из таблицы. В следующем примере мы с Вами сделаем выборку данных, а затем выведем результат:

$mysqli = @new mysqli("localhost", "Admin", "pass", "mybase");
if (mysqli_connect_errno()) {
echo "Подключение невозможно: ".mysqli_connect_error();
}
$result_set = $mysqli->
while ($row = $result_set->fetch_assoc()) {
print_r($row);
echo "
";
}
$result_set->close();
$mysqli->close();
?>

Для начала немного поясню, что из себя представляет result_set . Result_set - это таблица с результатом. У этой таблицы есть набор записей (строки таблицы). И для вывода всех записей надо перебрать каждую строку таблицы и вывести её. А теперь поясняю пример: после отправки запроса у нас формируется result_set . Затем мы в цикле присваиваем переменной row значение очередной строки, то есть одномерный массив, который возвращает метод fetch_assoc() . Когда все строки закончатся, метод fetch_assoc() вернёт false , и будет произведён выход из цикла. Внутри цикла while мы просто выводим массив с использованием отладочной функции print_r() , хотя, безусловно, можно было бы вывести с использованием foreach , но сейчас это не нужно.

Давайте кратко подведём итог, как нужно работать с result_set :

  1. Получить result_set , отправив соответствующий запрос к базе данных.
  2. В цикле на каждой итерации присваивать следующую строку (запись) из result_set с использованием метода fetch_assoc() некоторой переменной row . Дальше Вы можете работать с этой переменной как с одномерным ассоциативным массивом, у которого ключи - это названия полей таблицы, а значения соответствуют текущей записи.
  3. Обязательно закройте result_set методом close() , чтобы осводить ресурсы.

Как Вы заметили, метод fetch_assoc() возвращает всегда следующую запись. То есть сначала 1-ю, потом 2-ю, потом 3-ю и так далее. Если у Вас есть неплохой опыт программирования, то Вы сразу догадаетесь, что это происходит благодаря внутреннему указателю, который Вы, разумеется, можете двигать. Где это используется? Например, это может использоваться, когда Вам необходимо поработать с result_set не 1 , а 2 и более раз. Чтобы заново не формировать тот же запрос, можно просто передвинуть указатель в начало. И тогда можно снова заниматься перебором result_set с помощью метода fetch_assoc().

Для изменения положения указателя существует метод data_seek() , который принимает целое число от 0 до "количества записей - 1 ", соответственно указатель встаёт на соответствующую параметру запись:

$mysqli = @new mysqli("localhost", "Admin", "pass", "mybase");
if (mysqli_connect_errno()) {
echo "Подключение невозможно: ".mysqli_connect_error();
}
$result_set = $mysqli->query("SELECT * FROM mytable");
$result_set->num_rows;
while ($row = $result_set->fetch_assoc()) {
print_r($row);
echo "
";
}
$result_set->data_seek(0);
while ($row = $result_set->fetch_assoc()) {
print_r($row);
echo "
";
}
$result_set->close();
$mysqli->close();
?>

В этом примере мы вывели количество записей в result_set с помощью свойства num_rows . А также познакомились с методом data_seek() . То есть мы перебрали весь результат, затем вернули указатель на 0-ю запись и вновь перебрали результат.

В этой статье мы с Вами повторили подключение к базе данных и закрытие подключения. А также узнали, как отправлять запросы к базе данных через PHP . Узнали, как получать result_set и как работать с ним. Это всё, что Вам необходимо знать для успешной работы с MySQL в PHP .

Синтаксис:

* где fields1 — поля для выборки через запятую, также можно указать все поля знаком *; table — имя таблицы, из которой вытаскиваем данные; conditions — условия выборки; fields2 — поле или поля через запятую, по которым выполнить сортировку; count — количество строк для выгрузки.
* запрос в квадратных скобках не является обязательным для выборки данных.

Простые примеры использования select

1. Обычная выборка данных:

> SELECT * FROM users

2. Выборка данных с объединением двух таблиц (JOIN):

SELECT u.name, r.* FROM users u JOIN users_rights r ON r.user_id=u.id

* в данном примере идет выборка данных с объединением таблиц users и users_rights . Объединяются они по полям user_id (в таблице users_rights) и id (users). Извлекается поле name из первой таблицы и все поля из второй.

3. Выборка с интервалом по времени и/или дате

а) известна точка начала и определенный временной интервал:

* будут выбраны данные за последний час (поле date ).

б) известны дата начала и дата окончания:

25.10.2017 и 25.11.2017 .

в) известны даты начала и окончания + время:

* выбираем данные в промежутке между 25.03.2018 0 часов 15 минут и 25.04.2018 15 часов 33 минуты и 9 секунд .

г) вытаскиваем данные за определенные месяц и год:

* извлечем данные, где в поле date присутствуют значения для апреля 2018 года.

4. Выборка максимального, минимального и среднего значения:

> SELECT max(area), min(area), avg(area) FROM country

* max — максимальное значение; min — минимальное; avg — среднее.

5. Использование длины строки:

* данный запрос должен показать всех пользователей, имя которых состоит из 5 символов.

Примеры более сложных запросов или используемых редко

1. Объединение с группировкой выбранных данных в одну строку (GROUP_CONCAT):

* из таблицы users извлекаются данные по полю id , все они помещаются в одну строку, значения разделяются запятыми .

2. Группировка данных по двум и более полям:

> SELECT * FROM users GROUP BY CONCAT(title, "::", birth)

* итого, в данном примере мы сделаем выгрузку данных из таблицы users и сгруппируем их по полям title и birth . Перед группировкой мы делаем объединение полей в одну строку с разделителем :: .

3. Объединение результатов из двух таблиц (UNION):

> (SELECT id, fio, address, "Пользователи" as type FROM users)
UNION
(SELECT id, fio, address, "Покупатели" as type FROM customers)

* в данном примере идет выборка данных из таблиц users и customers .

4. Выборка средних значений, сгруппированных за каждый час:

SELECT avg(temperature), DATE_FORMAT(datetimeupdate, "%Y-%m-%d %H") as hour_datetime FROM archive GROUP BY DATE_FORMAT(datetimeupdate, "%Y-%m-%d %H")

* здесь мы извлекаем среднее значение поля temperature из таблицы archive и группируем по полю datetimeupdate (с разделением времени за каждый час).

Вставка (INSERT)

Синтаксис 1:

> INSERT INTO

() VALUES ()

Синтаксис 2:

> INSERT INTO

VALUES ()

* где table — имя таблицы, в которую заносим данные; fields — перечисление полей через запятую; values — перечисление значений через запятую.
* первый вариант позволит сделать вставку только по перечисленным полям — остальные получат значения по умолчанию. Второй вариант потребует вставки для всех полей.

Примеры использования insert

1. Вставка нескольких строк одним запросом:

> INSERT INTO cities ("name", "country") VALUES ("Москва", "Россия"), ("Париж", "Франция"), ("Фунафути" ,"Тувалу");

* в данном примере мы одним SQL-запросом добавим 3 записи.

2. Вставка из другой таблицы (копирование строк, INSERT + SELECT):

* извлекаем все записи из таблицы cities , названия которых начинаются на «М» и заносим в таблицу cities-new .

Обновление (UPDATE)

Синтаксис:

* где table — имя таблицы; field — поле, для которого будем менять значение; value — новое значение; conditions — условие (без него делать update опасно — можно заменить все данные во всей таблице).

Обновление с использованием замены (REPLACE):

UPDATE

SET = REPLACE(, "<что меняем>", "<на что>");

UPDATE cities SET name = REPLACE(name, "Масква", "Москва");

Если мы хотим перестраховаться, результат замены можно сначала проверить с помощью SELECT:

Удаление (DELETE)

Синтаксис:

* где table — имя таблицы; conditions — условие (как и в случае с UPDATE, использовать DELETE без условия опасно — СУБД не запросит подтверждения, а просто удалит все данные).

Создание таблицы

Синтаксис:

> CREATE TABLE

( , )

> CREATE TABLE IF NOT EXISTS `users_rights` (
`id` int(10) unsigned NOT NULL,
`user_id` int(10) unsigned NOT NULL,
`rights` int(10) unsigned NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

* где table — имя таблицы (в примере users_rights ); field1, field2 — имя полей (в примере создается 3 поля — id, user_id, rights ); options1, options2 — параметры поля (в примере int(10) unsigned NOT NULL ); table options — общие параметры таблицы (в примере ENGINE=InnoDB DEFAULT CHARSET=utf8 ).

Использование запросов в PHP

Подключаемся к базе данных:

mysql_connect ("localhost", "login", "password") or die ("MySQL connect error");
mysql_select_db ("db_name");
mysql_query("SET NAMES "utf8"");

* где подключение выполняется к базе на локальном сервере (localhost ); учетные данные для подключения — login и password (соответственно, логин и пароль); в качестве базы используется db_name ; используемая кодировка UTF-8 .

Также можно создать постоянное подключение:

mysql_pconnect ("localhost", "login", "password") or die ("MySQL connect error");

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

Завершить подключение:

* в PHP выполняется автоматически, кроме постоянных подключений (mysql_pconnect).

Запрос к MySQL (Mariadb) в PHP делается функцией mysql_query(), а извлечение данных из запроса — mysql_fetch_array():

$result = mysql_query("SELECT * FROM users");
while ($mass = mysql_fetch_array($result)) {
echo $mass . "
";
}

* в данном примере выполнен запрос к таблице users . Результат запроса помещен в переменную $result . Далее используется цикл while , каждая итерация которого извлекает массив данных и помещает его в переменную $mass — в каждой итерации мы работаем с одной строкой базы данных.

Используемая функция mysql_fetch_array() возвращает ассоциативный массив, с которым удобно работать, но есть еще альтернатива — mysql_fetch_row(), которая возвращает обычный нумерованный массив.

Экранирование

При необходимости включения в строку запроса спецсимвола, например, %, необходимо использовать экранирование с помощью символа обратного слэша — \

Например:

* если выполнить такой запрос без экранирования, знак %, будет восприниматься как любое количество символов после 100.

На этом все. Если Вам нужно помочь с выполнением запроса, пишите мне на почту


Содержание статьи
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, однако, он поддерживает блокировку строк, что является положительной стороной при масштабировании. Поэтому сказать, что одно лучше другого нельзя, да и не правильно, нужно выбирать тип исходя из своих потребностей.