Установка MySQL:
Continue reading »
http://dev.mysql.com/doc/refman/5.0/en/comparison-operators.html
Не знал про COALESCE – функцию, которая возвращает первое ненулевое значение из переданных параметров.
Перечислю основное.
Версия 5.0 (http://dev.mysql.com/doc/refman/5.0/en/mysql-nutshell.html):
- Курсоры
- Хранимые функции
- Триггеры
- VIEW
- INFORMATION_SCHEMA (база о базах данных сервера)
- Тип данных VARCHAR
Версия 5.1 (http://dev.mysql.com/doc/refman/5.1/en/mysql-nutshell.html):
- Оптимизация оптимизатора (особенно GROUP BY)
- InnoDB plugin
- Partitioning
- Row based replication
Версия 5.4 (http://dev.mysql.com/doc/refman/5.4/en/mysql-nutshell.html):
- Улучшена масштабируемость
- Изменение подсистемы ввода-вывода InnoDB
Top 1000 SQL Performance Tips
Continue reading »
По этому адресу – список полезных инструментов для тюнинга mySQL:
http://dev.mysql.com/doc/refman/5.1/en/mysql-nutshell.html
Ссылка на статью.
Для чего они нужны:
- чтобы проверить и предотвратить вставку некорректных данных
- чтобы изменить или отменить процедуры INSERT, UPDATE, DELETE
- чтобы отслеживать изменения данных внутри сесии.
Триггер – это фактически хранимая процедура, выполняющаяся при определённом событии, относящемся к определённым данным (хотя и с некоторыми нюансами).
Синтаксис:
CREATE TRIGGER <trigger name>
{ BEFORE | AFTER }
{ INSERT | UPDATE | DELETE }
ON <table name>
FOR EACH ROW
<triggered SQL statement>
При этом доступны специфичные пространства имён OLD и NEW в зависимости от контекста (INSERT, UPDATE, DELETE)
CREATE TRIGGER t21_au BEFORE UPDATE ON t22 FOR EACH ROW BEGIN SET @old = OLD . s1; SET @new = NEW.s1; END;//
Пример использования для предотвращения вставки некорректных данных
CREATE TABLE t25 (s1 INT, s2 CHAR(5), PRIMARY KEY (s1)) ENGINE=INNODB// CREATE TRIGGER t25_bi BEFORE INSERT ON t25 FOR EACH ROW IF LEFT(NEW.s2,1)<>'A' THEN SET NEW.s1=0; END IF;// CREATE TRIGGER t25_bu BEFORE UPDATE ON t25 FOR EACH ROW IF LEFT(NEW.s2,1)<>'A' THEN SET NEW.s1=0; END IF;// INSERT INTO t25 VALUES (0,'a') /* priming the pump */ // INSERT INTO t25 VALUES (5,'b') /* gets error '23000' */ //
Для тех, кто не знает, что это такое – ссылка
Вкратце: созздаёт, фактически, «временную таблицу» (более правильно сказать – виртуальную таблицу или результат выборки в виде таблицы), в которой могут храниться данные из других таблиц и результаты применения аггрегирующих функций к ним. При этом если хранятся только данные, то эта таблица обновляется при обновлении входящих в её состав таблиц.
Но оказывается, что, как и многие нововведения (хранимые процедуры должны перекомпилироваться заново при начале сессии, если использовать подзапросы – очень много запросов получается), это тоже имеет очень большие проблемы с производительностью (ссылка).
Вкратце:
неудобно искать проблемы в запросах (вроде как обращаешься к одной таблице, а на деле – нет), создаётся временная таблица без индексов. Также есть проблемы у mySQL при оптимизации запросов при обращении к VIEW.
SELECT
t.TABLE_SCHEMA AS `db`, t.TABLE_NAME AS `table`, s.INDEX_NAME AS `index name`
, s.COLUMN_NAME AS `field name`, s.SEQ_IN_INDEX `seq in index`, s2.max_columns AS `# cols`
, s.CARDINALITY AS `card`, t.TABLE_ROWS AS `est rows`
, ROUND(((s.CARDINALITY / IFNULL(t.TABLE_ROWS, 0.01)) * 100), 2) AS `sel %`
FROM INFORMATION_SCHEMA.STATISTICS s
INNER JOIN INFORMATION_SCHEMA.TABLES t
ON s.TABLE_SCHEMA = t.TABLE_SCHEMA AND s.TABLE_NAME = t.TABLE_NAME
INNER JOIN (
SELECT TABLE_SCHEMA, TABLE_NAME, INDEX_NAME, MAX(SEQ_IN_INDEX) AS max_columns
FROM INFORMATION_SCHEMA.STATISTICS WHERE TABLE_SCHEMA != ‘mysql’
GROUP BY TABLE_SCHEMA, TABLE_NAME, INDEX_NAME
) AS s2
ON s.TABLE_SCHEMA = s2.TABLE_SCHEMA AND s.TABLE_NAME = s2.TABLE_NAME AND s.INDEX_NAME = s2.INDEX_NAME
WHERE t.TABLE_SCHEMA != ‘mysql’ /* Filter out the mysql system DB */
AND t.TABLE_ROWS > 10 /* Only tables with some rows */
AND s.CARDINALITY IS NOT NULL /* Need at least one non-NULL value in the field */
AND (s.CARDINALITY / IFNULL(t.TABLE_ROWS, 0.01)) < 1.00 /* unique indexes are perfect anyway */
ORDER BY `sel %`, s.TABLE_SCHEMA, s.TABLE_NAME /* DESC for best non-unique indexes */
LIMIT 10;
Это из лекции товарища Jay Pipes
оригинал; полная цитата:
Сегодня был неожиданно удивлен, какие удобные штуки таит в себе MySQL.
Хочу представить вашему вниманию фичу MySQL — профайлинг.
Появилась она начиная с версии 5.0.37.
Всего парой запросов можно узнать, какими запросами формируется страница (для веб-девелоперов)
и почему она тормозит.
И раньше подобный функционал был доступен, но пользоваться журналом запросов не в пример сложнее.
Итак, как пользоваться:
mysql> set profiling=1;
mysql> select count(*) from comment;
mysql> select count(*) from message;
mysql> show profiles;
+———-+————+——————————+
| Query_ID | Duration | Query |
+———-+————+——————————+
| 1 | 0.00012700 | select count(*) from comment |
| 2 | 0.00014200 | select count(*) from message |
+———-+————+——————————+
2 rows in set (0.00 sec)
Вуаля! Все выполненные запросы за сессию с временем выполнения.
На мой взгляд очень просто и сверх-удобно.
Можно пойти дальше, и узнать подробно на что тратилось время по каждому запросу:
mysql> show profile for query 1;
+——————————–+———-+
| Status | Duration |
+——————————–+———-+
| starting | 0.000015 |
| checking query cache for query | 0.000021 |
| checking permissions | 0.000003 |
| Opening tables | 0.000007 |
| System lock | 0.000004 |
| Table lock | 0.000023 |
| init | 0.000005 |
| optimizing | 0.000005 |
| executing | 0.000025 |
| end | 0.000003 |
| end | 0.000001 |
| query end | 0.000002 |
| storing result in query cache | 0.000003 |
| freeing items | 0.000003 |
| closing tables | 0.000004 |
| logging slow query | 0.000002 |
| cleaning up | 0.000001 |
+——————————–+———-+
17 rows in set (0.00 sec)
Подробнее о профайлинге в статье: Using the New MySQL Query Profiler
Upd: как точно подметил zayceslavshow profiles по умолчанию показывает профили для 15 запросов. Кол-во запрсов можно увеличить с помощью параметра profiling_history_size, но не более чем до 100.
mysql> set profiling=1;
mysql> set profiling_history_size=100;