Приховані особливості MySQL


101

Я працюю з Microsoft SQL Server вже багато років, але лише нещодавно почав використовувати MySQL у своїх веб-додатках, і я прагну знань.

Щоб продовжити довгий ряд питань "прихованої функції" , я хотів би знати будь-які приховані або зручні функції MySQL, які, сподіваюся, покращать мої знання про цю базу даних з відкритим кодом.

Відповіді:


161

З тих пір, як ти виставив щедрість, я поділюся своїми важкими виграними таємницями ...

Загалом, всі SQL, які я сьогодні налаштував, потрібні за допомогою підзапитів. Прийшовши зі світу баз даних Oracle, речі, які я сприйняв як належне, не працювали так само з MySQL. І моє читання про налаштування MySQL змушує мене зробити висновок, що MySQL відстає від Oracle з точки зору оптимізації запитів.

Незважаючи на те, що прості запити, необхідні для більшості програм B2C, можуть працювати добре для MySQL, але для більшості зведених типів запитів, необхідних для Intelligence Reporting, потрібне досить небагато планування та переорганізації SQL запитів, щоб керувати MySQL, щоб швидше їх виконувати.

Адміністрація:

max_connections- кількість одночасних з'єднань. Значення за замовчуванням - 100 з'єднань (151 з 5,0) - дуже мало.

Примітка:

з'єднання займають пам’ять, і ваша ОС може не в змозі обробити багато з'єднань.

Бінарні файли MySQL для Linux / x86 дозволяють мати до 4096 одночасних з'єднань, але самостійно складені бінарні файли часто мають менший ліміт.

Встановіть table_cache відповідно до кількості ваших відкритих таблиць та одночасних з'єднань. Слідкуйте за значенням open_tables, і якщо воно швидко зростає, вам потрібно буде збільшити його розмір.

Примітка:

Два попередні параметри можуть вимагати багато відкритих файлів. 20 + max_connections + table_cache * 2 - це хороша оцінка того, що вам потрібно. MySQL в Linux має опцію open_file_limit, встановивши цей ліміт.

Якщо у вас є складні запити sort_buffer_size та tmp_table_size, ймовірно, будуть дуже важливими. Значення залежатимуть від складності запиту та наявних ресурсів, але 4Mb та 32Mb відповідно рекомендуються вихідні точки.

Примітка. Це значення "за з'єднання", серед read_buffer_size, read_rnd_buffer_size та деяких інших, тобто це значення може знадобитися для кожного з'єднання. Отже, враховуйте навантаження та наявний ресурс при встановленні цих параметрів. Наприклад, sort_buffer_size виділяється лише в тому випадку, якщо MySQL потрібно зробити сортування. Примітка: будьте обережні, щоб не втратило пам'ять.

Якщо у вас встановлено багато підключень (наприклад, веб-сайт без стійких з'єднань), ви можете покращити продуктивність, встановивши nit_cache_size на ненульове значення. 16 - це гарне значення для початку. Збільшуйте значення до тих пір, поки ваші теми_створення не зростуться дуже швидко.

ПЕРШИЙ КЛЮЧ:

У таблиці може бути лише один стовпець AUTO_INCREMENT, він повинен бути індексований, і він не може мати значення DEFAULT

KEY - це зазвичай синонім INDEX. Ключовий атрибут PRIMARY KEY також може бути вказаний як просто KEY, коли він вказаний у визначенні стовпця. Це було реалізовано для сумісності з іншими системами баз даних.

ПЕРВИЧНИЙ КЛЮЧ - це унікальний індекс, де всі ключові стовпці повинні бути визначені як НЕ НУЛЬНІ

Якщо індекс PRIMARY KEY або UNIQUE складається лише з одного стовпця з цілим типом, ви також можете посилатися на цей стовпець як "_rowid" у операторах SELECT.

У MySQL назва ПРИМІТНОГО КЛЮЧА - ПЕРВИЧНА

Наразі лише таблиці InnoDB (v5.1?) Підтримують зовнішні ключі.

Зазвичай ви створюєте всі необхідні індекси під час створення таблиць. Будь-який стовпець, оголошений як PRIMARY KEY, KEY, UNIQUE, або INDEX, буде індексований.

NULL означає "не має значення". Щоб перевірити наявність NULL, ви не можете використовувати оператори порівняння арифметики, такі як =, <або <>. Використовуйте оператори IS NULL, а НЕ NULL:

NO_AUTO_VALUE_ON_ZERO пригнічує автоматичне збільшення на 0, так що лише NULL генерує наступний номер послідовності. Цей режим може бути корисним, якщо 0 зберігається в стовпці AUTO_INCREMENT таблиці. (До речі, зберігання 0 - це не рекомендується.)

Щоб змінити значення лічильника AUTO_INCREMENT, який буде використовуватися для нових рядків:

ALTER TABLE mytable AUTO_INCREMENT = value; 

або SET INSERT_ID = значення;

Якщо не вказано інше, значення розпочнеться з: 1000000 або вказати його таким чином:

...) ENGINE = MyISAM DEFAULT CHARSET = latin1 AUTO_INCREMENT = 1

ЧАСИ:

Значення стовпців TIMESTAMP перетворюються з поточного часового поясу в UTC для зберігання, а з UTC у поточний часовий пояс для пошуку.

http://dev.mysql.com/doc/refman/5.1/uk/timestamp.html Для одного стовпця TIMESTAMP у таблиці ви можете призначити поточну позначку часу як значення за замовчуванням та значення автоматичного оновлення.

на що слід звернути увагу при використанні одного з цих типів у пункті WHERE, найкраще робити WHERE datecolumn = FROM_UNIXTIME (1057941242), а не WHERE UNIX_TIMESTAMP (datecolumn) = 1057941242. Якщо останні не скористаються індексом на цьому стовпчику.

http://dev.mysql.com/doc/refman/5.1/en/date-and-time-functions.html

 UNIX_TIMESTAMP() 
 FROM_UNIXTIME() 
 UTC_DATE()
 UTC_TIME()
 UTC_TIMESTAMP()

якщо ви перетворите дату в часову позначку unix в MySQL:
а потім додайте до неї 24 години:
а потім конвертуйте її назад у дату, вона магічно втрачає годину!

Ось що відбувається. При перетворенні часової позначки unix на дату часу враховується часовий пояс, і саме так трапляється, що між 28 та 29 жовтня 2006 року ми втратили літній час і втратили годину.

Починаючи з MySQL 4.1.3, функції CURRENT_TIMESTAMP (), CURRENT_TIME (), CURRENT_DATE () та FROM_UNIXTIME () повертають значення у поточному часовому поясі підключення , яке доступне як значення системної змінної time_zone. Крім того, UNIX_TIMESTAMP () припускає, що його аргументом є значення дати в поточному часовому поясі.

Поточний параметр часового поясу не впливає на значення, відображені такими функціями, як UTC_TIMESTAMP (), або значення у стовпцях DATE, TIME або DATETIME.

ПРИМІТКА: ON UPDATE ТОЛЬко оновлює DateTime, якщо поле змінено. Якщо UPDATE не призводить до зміни полів, DateTime НЕ оновляється!

Крім того, перша TIMESTAMP завжди є AUTOUPDATE за замовчуванням, навіть якщо не вказано

Працюючи з датами, я майже завжди прихиляюсь до Джуліана Дати, оскільки математика даних - це проста справа додавання чи віднімання цілих чисел та секунд з півночі з тієї ж причини. Рідко мені потрібна часова резолюція більш тонкої зернистості, ніж секунди.

І те і інше можна зберігати у вигляді 4-байтного цілого числа, і якщо простір дійсно обмежений, його можна об'єднати в час UNIX (секунди з епохи 1/1/1970) у вигляді безпідписаного цілого числа, яке буде добре приблизно до 2106 року:

'сек за 24 год = 86400

"Максимальна цінність з підписаним цілим числом = 2147,483,647 - може тривати 68 років секунд

"Непідписаний цілий число max = 4 294 967 295 - може тривати 136 років секунд

Бінарний протокол:

MySQL 4.1 представив двійковий протокол, який дозволяє надсилати та повертати нестрокові значення даних у рідному форматі без перетворення у строковий формат та з нього. (Дуже корисно)

Крім того, mysql_real_query () швидше, ніж mysql_query (), оскільки він не викликає strlen () для роботи над рядком заяви.

http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html Двійковий протокол підтримує підготовлені на сервері оператори та дозволяє передавати значення даних у рідному форматі. Під час попередніх випусків MySQL 4.1 двійковий протокол зазнав неабиякого перегляду.

Ви можете використовувати макрос IS_NUM (), щоб перевірити, чи має поле числовий тип. Передайте значення типу IS_NUM () і воно оцінює на TRUE, якщо поле числове:

Варто зазначити, що бінарні дані МОЖЛИВІ відправлятись у звичайний запит, якщо ви уникаєте від нього та пам'ятаєте, що MySQL вимагає лише того, щоб нахил косою рисою та символом цитати. Отже, це дійсно простий спосіб ВСТАВИТИ коротші бінарні рядки, наприклад, зашифровані / сольові паролі.

Основний сервер:

http://www.experts-exchange.com/Database/MySQL/Q_22967482.html

http://www.databasejournal.com/features/mysql/article.php/10897_3355201_2

ВИКЛЮЧИТИ СЛАВ ЗА ЗАМОВЛЕННЯ . до slave_user ІДЕНТИФІКОВАНО "slave_password"

#Master Binary Logging Config  STATEMENT causes replication 
              to be statement-based -  default

log-bin=Mike
binlog-format=STATEMENT
server-id=1            
max_binlog_size = 10M
expire_logs_days = 120    


#Slave Config
master-host=master-hostname
master-user=slave-user
master-password=slave-password
server-id=2

Бінарний файл журналу повинен читати:

http://dev.mysql.com/doc/refman/5.0/en/binary-log.html

http://www.mydigitallife.info/2007/10/06/how-to-read-mysql-binary-log-files-binlog-with-mysqlbinlog/

http://dev.mysql.com/doc/refman/5.1/uk/mysqlbinlog.html

http://dev.mysql.com/doc/refman/5.0/en/binary-log.html

http://dev.mysql.com/doc/refman/5.1/uk/binary-log-setting.html

Ви можете видалити всі бінарні файли журналу за допомогою оператора RESET MASTER або їх підмножину за допомогою PURGE MASTER

--result-file = binlog.txt TrustedFriend-bin.000030

Нормалізація:

http://dev.mysql.com/tech-resources/articles/intro-to-normalization.html

Функції АДС

http://www.koders.com/cpp/fid10666379322B54AD41AEB0E4100D87C8CDDF1D8C.aspx

http://souptonuts.sourceforge.net/readme_mysql.htm

Типи даних:

http://dev.mysql.com/doc/refman/5.1/uk/storage-requirements.html

http://www.informit.com/articles/article.aspx?p=1238838&seqNum=2

http://bitfilm.net/2008/03/24/saving-bytes-efficient-data-storage-mysql-part-1/

Варто зазначити, що на змішаній таблиці з CHAR та VARCHAR mySQL змінить значення CHAR на VARCHAR

RecNum integer_type UNIGNED NOT NULL AUTO_INCREMENT, PRIMARY KEY (RecNum)

MySQL завжди представляє дати з першим роком року, відповідно до стандартних специфікацій SQL та ISO 8601

Різне:

Якщо вимкнути деякі функції MySQl, це призведе до менших файлів даних та швидшого доступу. Наприклад:

--datadir вкаже каталог даних і

--skip-innodb відключить варіант nev і заощадить 10-20M

Більше тут http://dev.mysql.com/tech-resources/articles/mysql-c-api.html

Завантажте розділ 7 - безкоштовно

InnoDB є транзакційним, але є продуктивність, що додається до нього. Я визнав таблиці MyISAM достатніми для 90% моїх проектів. Таблиці, не безпечні для транзакцій (MyISAM), мають свої власні переваги, які виникають через те, що:

немає накладних транзакцій:

Набагато швидше

Менші вимоги до місця на диску

Для оновлення потрібно менше пам’яті

Кожна таблиця MyISAM зберігається на диску в трьох файлах. У файлах є імена, які починаються з імені таблиці та мають розширення для позначення типу файлу. Файл .frm зберігає формат таблиці. Файл даних має розширення .MYD (MYData). Файл індексу має розширення .MYI (MYIndex).

Ці файли можна скопіювати до місця зберігання недоторканим без використання функції резервного копіювання MySQL Administrators, яка забирає багато часу (так це відновлення)

Хитрість полягає в тому, щоб зробити копію цих файлів, а потім ЗРОБИТИ таблицю. Після повернення файлів MySQl розпізнає їх та оновить відстеження таблиці.

Якщо потрібно створити резервну копію / відновлення,

Відновлення резервної копії або імпорт із існуючого файлу дампа може зайняти багато часу, залежно від кількості індексів та первинних ключів у кожної таблиці. Ви можете швидко прискорити цей процес, змінивши оригінальний файл дампа, оточуючи його наступним чином:

SET AUTOCOMMIT = 0;
SET FOREIGN_KEY_CHECKS=0;

.. your dump file ..

SET FOREIGN_KEY_CHECKS = 1;
COMMIT;
SET AUTOCOMMIT = 1;

Щоб значно збільшити швидкість перезавантаження, додайте команду SQL SET AUTOCOMMIT = 0; на початку дамп-файлу та додайте COMMIT; командувати до кінця.

За замовчуванням функція автокомісії увімкнена, тобто кожна команда вставки у файлі дампа буде розглядатися як окрема транзакція та записуватися на диск до початку наступної. Якщо не додати ці команди, перезавантаження великої бази даних в InnoDB може зайняти багато годин ...

Максимальний розмір рядка в таблиці MySQL - 65 555 байт

Максимальна ефективна довжина VARCHAR в MySQL 5.0.3 та on = максимальний розмір рядка (65,535 байт)

Значення VARCHAR не заповнюються, коли вони зберігаються. Проміжки проміжку зберігаються, коли значення зберігаються та отримуються відповідно до стандартних SQL.

Значення CHAR і VARCHAR в MySQL порівнюються без урахування пробілів.

Використання CHAR прискорить ваш доступ лише в тому випадку, якщо весь запис має фіксований розмір. Тобто, якщо ви використовуєте будь-який об’єкт змінного розміру, ви можете також зробити всі вони змінними розмірами. Ви не набираєте швидкості, використовуючи CHAR у таблиці, яка також містить VARCHAR.

Ліміт VARCHAR в 255 символів був підвищений до 65535 символів станом на MySQL 5.0.3

Повнотекстовий пошук підтримується лише для таблиць MyISAM.

http://dev.mysql.com/doc/refman/5.0/uk/fulltext-search.html

Стовпці BLOB не мають набору символів, а сортування та порівняння ґрунтуються на числових значеннях байтів у значеннях стовпців

Якщо жорсткий режим SQL не ввімкнено, і ви присвоюєте значення стовпцю BLOB або TEXT, що перевищує максимальну довжину стовпця, це значення обрізається, щоб відповідати, і створюється попередження.

Корисні команди:

перевірити суворий режим: SELECT @@ global.sql_mode;

вимкнути суворий режим:

SET @@ global.sql_mode = '';

SET @@ global.sql_mode = 'MYSQL40'

або видалити: sql-mode = "STRICT_TRANS_TABLES, ...

ПОКАЖІТЬСЯ КОЛИНИ З mytable

ВИБІРТЕ макс. (Ім’я), ЯК virtualcolumnВІД мітового ЗАМОВЛЕННЯ ПО віртуальній колонці

http://dev.mysql.com/doc/refman/5.0/uk/group-by-hidden-fields.html

http://dev.mysql.com/doc/refman/5.1/uk/information-functions.html#function_last-insert-id last_insert_id ()

отримує PK останнього рядка, вставленого в поточний максимум потоку (pkcolname), отримує останній PK в цілому.

Примітка: якщо таблиця порожня, max (pkcolname) повертає 1 mysql_insert_id () перетворює тип повернення нативної функції MySQL C API mysql_insert_id () у тип long (названий int у PHP).

Якщо ваш стовпець AUTO_INCREMENT містить тип стовпця BIGINT, значення, повернене mysql_insert_id (), буде неправильним. Замість цього використовуйте внутрішню функцію MySQL SQL LAST_INSERT_ID () у запиті SQL.

http://dev.mysql.com/doc/refman/5.0/uk/information-functions.html#function_last-insert-id

Просто зауважте, що, намагаючись вставити дані в таблицю, ви отримаєте помилку:

Unknown column the first bit of data what you want to put into the table in field list

використовуючи щось подібне

INSERT INTO table (this, that) VALUES ($this, $that)

це тому, що у вас немає апостроф навколо значень, які ви намагаєтеся вписати в таблицю. Тож слід змінити код на:

INSERT INTO table (this, that) VALUES ('$this', '$that') 

нагадування, що `` використовуються для визначення полів, баз даних або таблиць MySQL, а не значень;)

Під час запиту втрачено з'єднання з сервером:

http://dev.mysql.com/doc/refman/5.1/uk/gone-away.html

http://dev.mysql.com/doc/refman/5.1/uk/packet-too-large.html

http://dev.mysql.com/doc/refman/5.0/en/server-parameters.html

http://dev.mysql.com/doc/refman/5.1/uk/show-variables.html

http://dev.mysql.com/doc/refman/5.1/uk/option-files.html

http://dev.mysql.com/doc/refman/5.1/en/error-log.html

Налаштування запитів

http://www.artfulsoftware.com/infotree/queries.php?&bw=1313

Ну, це могло б бути достатньо, щоб заробити бонус, я б подумав ... Плоди багатьох годин і безліч проектів з великою безкоштовною базою даних. Я розробляю сервери даних додатків на платформах Windows, здебільшого за допомогою MySQL. Найгірший безлад, який мені довелося виправити, був

Кінцевий кошмар бази даних спадщини MySQL

Для цього потрібна низка застосунків, щоб обробити таблиці в щось корисне, використовуючи багато згаданих тут трюків.

Якщо ви виявили це надзвичайно корисним, висловіть свою подяку, проголосувавши його.

Ознайомтесь і з іншими моїми статтями та документами на веб-сайті: www.coastrd.com


22

Один з не так прихованої особливістю MySQL є те , що це не дуже добре бути SQL поступливий, ну, не помилки на самому справі, але, все більше підводних каменів ... :-)


Інші особи знають, що цей список був цінним при переході від MSSQL до MySQL. Ура Мат.
GateKiller

Багато з них отримані з попередніх версій MySQL.
jmucchiello

для одного, я не думаю, що коли-небудь вдасться поставити значення NULL у полі часової позначки.
мат

3
MySQL не особливо гірший, оскільки він сумісний з SQL, ніж багато інших баз даних; до тих пір, поки ви дотримуєтесь розумного підмножини SQL, ви, як правило, уникаєте gotchas - що більше, ніж можна сказати, наприклад. Сумно відомі порожні рядки Oracle NULL.
bobince

1
Ви можете вимкнути деякі роботи,SET SESSION sql_mode='ANSI';
Корнель,

21

Команда, щоб дізнатися, які таблиці зараз є в кеші:

mysql> SHOW open TABLES FROM test;
+----------+-------+--------+-------------+
| DATABASE | TABLE | In_use | Name_locked |
+----------+-------+--------+-------------+
| test     | a     |      3 |           0 |
+----------+-------+--------+-------------+
1 row IN SET (0.00 sec)

блогу продуктивності MySQL )


15

Команда з'ясувати, хто що робить:

mysql> show processlist;
show processlist;
+----+-------------+-----------------+------+---------+------+----------------------------------+------------------+
| Id | User        | Host            | db   | Command | Time | State                            | Info             |
+----+-------------+-----------------+------+---------+------+----------------------------------+------------------+
|  1 | root        | localhost:32893 | NULL | Sleep   |    0 |                                  | NULL             |
|  5 | system user |                 | NULL | Connect |   98 | Waiting for master to send event | NULL             |
|  6 | system user |                 | NULL | Connect | 5018 | Reading event from the relay log | NULL             |
+-----+------+-----------+---------+---------+-------+-------+------------------+
3 rows in set (0.00 sec) 

І ви можете вбити процес за допомогою:

mysql>kill 5 

5
Також ПОКАЗНАЙТЕ ПОВНИЙ ПРОЦЕСЛІСТ, якщо ви не хочете, щоб запити були усіченими.
Грег

11

Мені особливо подобається вбудована підтримка MySQL для inet_ntoa()та inet_aton(). Це робить обробку IP-адрес у таблицях дуже однозначною (принаймні до тих пір, поки вони є лише IPv4-адресами!)


2
PostgreSQL має дуже приємний тип inet, який обробляє ipv4 та ipv6 дуже нікчемно :-)
мат

Мені їх теж подобалося, але навіть не потрібно їх використовувати. +1 для Postgres.
Корнель

11

Я люблю on duplicate key(AKA upsert, merge) за всілякі лічильники, створені ліниво:

insert into occurances(word,count) values('foo',1),('bar',1) 
  on duplicate key cnt=cnt+1

Ви можете вставити багато рядків в один запит і негайно обробити повторюваний індекс для кожного з рядків.


10

Знову ж таки - не дуже приховані функції, але дуже зручні:

Особливість

Легко захопити DDL:

SHOW CREATE TABLE CountryLanguage

вихід:

CountryLanguage | CREATE TABLE countrylanguage (
  CountryCode char(3) NOT NULL DEFAULT '',
  Language char(30) NOT NULL DEFAULT '',
  IsOfficial enum('T','F') NOT NULL DEFAULT 'F',
  Percentage float(4,1) NOT NULL DEFAULT '0.0',
  PRIMARY KEY (CountryCode,Language)
) ENGINE=MyISAM DEFAULT CHARSET=latin1

Особливість: Функція агрегації GROUP_CONCAT () Створює об'єднаний рядок з його аргументів на деталі та об'єднує шляхом об'єднання аргументів у групу.

Приклад 1: простий

SELECT   CountryCode
,        GROUP_CONCAT(Language) AS List
FROM     CountryLanguage
GROUP BY CountryCode             

Вихід:

+-------------+------------------------------------+
| CountryCode | List                               |
+-------------+------------------------------------+
| ABW         | Dutch,English,Papiamento,Spanish   |
. ...         . ...                                .
| ZWE         | English,Ndebele,Nyanja,Shona       |
+-------------+------------------------------------+

Приклад 2: кілька аргументів

SELECT   CountryCode
,        GROUP_CONCAT(
             Language
,            IF(IsOfficial='T', ' (Official)', '')
         )               AS List
FROM     CountryLanguage
GROUP BY CountryCode

Вихід:

+-------------+---------------------------------------------+
| CountryCode | List                                        |
+-------------+---------------------------------------------+
| ABW         | Dutch (Official),English,Papiamento,Spanish |
. ...         . ...                                         .
| ZWE         | English (Official),Ndebele,Nyanja,Shona     |
+-------------+---------------------------------------------+

Приклад 3: Використання спеціального роздільника

SELECT   CountryCode
,        GROUP_CONCAT(Language SEPARATOR ' and ') AS List
FROM     CountryLanguage
GROUP BY CountryCode

Вихід:

+-------------+----------------------------------------------+
| CountryCode | List                                         |
+-------------+----------------------------------------------+
| ABW         | Dutch and English and Papiamento and Spanish |
. ...         . ...                                          .
| ZWE         | English and Ndebele and Nyanja and Shona     |
+-------------+----------------------------------------------+

Приклад 4: Керування порядком елементів списку

SELECT   CountryCode
,        GROUP_CONCAT(
         Language
         ORDER BY CASE IsOfficial WHEN 'T' THEN 1 ELSE 2 END DESC
         ,        Language
         )               AS List
FROM     CountryLanguage
GROUP BY CountryCode

Вихід:

+-------------+------------------------------------+
| CountryCode | List                               |
+-------------+------------------------------------+
| ABW         | English,Papiamento,Spanish,Dutch,  |
. ...         . ...                                .
| ZWE         | Ndebele,Nyanja,Shona,English       |
+-------------+------------------------------------+

Особливість: COUNT (DISTINCT) з кількома виразами

Ви можете використовувати кілька виразів у виразі COUNT (DISTINCT ...) для підрахунку кількості комбінацій.

SELECT COUNT(DISTINCT CountryCode, Language) FROM CountryLanguage

Feature / Gotcha: Не потрібно включати неагреговані вирази до списку GROUP BY

Більшість RDBMS застосовують групу GROUP BY, сумісну з SQL92, яка вимагає, щоб усі неагреговані вирази у списку SELECT відображалися у групі BY. У цих RDBMS-повідомленнях це твердження:

SELECT     Country.Code, Country.Continent, COUNT(CountryLanguage.Language)
FROM       CountryLanguage 
INNER JOIN Country 
ON         CountryLanguage.CountryCode = Country.Code
GROUP BY   Country.Code

не вірно, оскільки список SELECT містить неагрегований стовпець Country.Continent, який не відображається у списку GROUP BY. У цих RDBMS-іх ви повинні або змінити список GROUP BY, щоб прочитати

GROUP BY   Country.Code, Country.Continent

або потрібно додати, наприклад, якийсь безглуздий агрегат до Country.Continent

SELECT     Country.Code, MAX(Country.Continent), COUNT(CountryLanguage.Language)

Тепер, справа в тому, що логічно немає нічого, що вимагає від Country.Continent бути посиленим. Дивіться, Country.Code - це первинний ключ таблиці Country. Country.Continent - це також стовпець із таблиці Country і, таким чином, за визначеннями функціонально залежить від первинного ключа Country.Code. Отже, у Country.Continent повинно існувати рівно одне значення для кожного окремого Country.Code. Якщо ви усвідомлюєте це, ніж ви розумієте, що не має сенсу агрегувати його (є лише одне значення, правильно), а також групувати його (оскільки це не зробить результат більш унікальним, оскільки ви вже групуєтесь за pk)

У будь-якому випадку - MySQL дозволяє включати неагреговані стовпці до списку SELECT, не вимагаючи також додавати їх до пункту GROUP BY.

Суть з цим полягає в тому, що MySQL не захищає вас у випадку, якщо вам трапляється використовувати неагрегований стовпець. Отже, такий запит:

SELECT     Country.Code, COUNT(CountryLanguage.Language), CountryLanguage.Percentage
FROM       CountryLanguage 
INNER JOIN Country 
ON         CountryLanguage.CountryCode = Country.Code
GROUP BY   Country.Code

Виконується без скарги, але стовпець CountryLanguage.Percentage буде містити безглуздість (тобто всі відсотки мов, одне з доступних значень відсотка буде вибрано випадковим чином або принаймні поза вашим контролем.

Дивіться: Debunking Group by Myths


Дозволення стовпців, не задекларованих у групі, - одна з моїх найменш улюблених функцій від Oracle. Це велика проблема, якщо ти звик до Oracle - він просто дозволяє запустити запит, результати виглядають правильно, але потім ти зрозумієш, що це не те, що ти думав, що це було.
mbafford

7

Команда "пейджер" у клієнті

Якщо у вас є, скажімо, 10 000 рядків у вашому результаті і хочете переглянути їх (Це передбачає доступні команди "менше" та "трійник", що, як правило, відбувається в Linux; в Windows YMMV.)

pager less
select lots_of_stuff FROM tbl WHERE clause_which_matches_10k_rows;

І ви отримаєте їх у "менш" переглядачі файлів, щоб ви могли їх красиво переглядати, шукати тощо.

Також

pager tee myfile.txt
select a_few_things FROM tbl WHERE i_want_to_save_output_to_a_file;

Зручно записуватимуть у файл.


на жаль, під вікнами, навіть якщо існують "менше" та "трійник", сам варіант пейджера не підтримується. нелегко все одно
Беррі Цакала

6

Деякі речі, які можуть вам бути цікавими:

<query>\G -- \G in the CLI instead of the ; will show one column per row
explain <query>; -- this will show the execution plan for the query


3

Ось кілька моїх порад - я про них в своєму блозі ( Посилання )

  1. Вам не потрібно використовувати знак "@" при оголошенні змінних.
  2. Ви повинні використовувати роздільник (за замовчуванням - ';'), щоб розмежувати кінець оператора - Посилання
  3. Якщо ви намагаєтеся перемістити дані між MS-SQL 2005 та mySQL, є кілька обручів для переходу через - Link
  4. Як збігаються з регістрових збігів у MySQL - посилання


3

Якщо ви використовуєте cmdline Mysq, ви можете взаємодіяти з командним рядком (на машинах Linux - не впевнений, чи є еквівалентний ефект на Windows), використовуючи крик / знак оклику. Наприклад:

\! cat file1.sql

відобразиться код для file1.sql. Щоб зберегти свою заяву та запит у файл, використовуйте інструмент "tee"

\T filename

щоб вимкнути це, використовуйте \ t

Нарешті, щоб запустити сценарій, який ви вже зберегли, використовуйте "ім'я вихідного файлу". Звичайно, нормальною альтернативою є пряме ім'я сценарію при запуску mysql з командного рядка:

    mysql -u root -p < case1.sql

Сподіваюсь, комусь це корисно!

Редагувати: Щойно запам'ятався ще один - при виклику mysql з командного рядка ви можете використовувати перемикач -t, щоб результат був у форматі таблиці - справжнє благо з деякими запитами (хоча, звичайно, завершення запитів з \ G, як згадується в іншому місці, також є корисна в цьому відношенні). Набагато більше про різні перемикачі Інструмент командного рядка

Щойно з'ясував акуратний спосіб змінити порядок сортування (зазвичай використовуйте Case ...) Якщо ви хочете змінити порядок сортування (можливо, сортувати на 1, 4, 3, 2 замість 1, 2, 3, 4) Ви можете використовувати функцію поля в межах Порядку за пунктом. Наприклад

Упорядкувати по полях (сортування_поля, 1,4,3,2)


3

Я не думаю, що це специфічно для MySQL, але приємно для мене:

Замість того, щоб писати

WHERE (x.id > y.id) OR (x.id = y.id AND x.f2 > y.f2) 

Можна просто написати

WHERE (x.id, x.f2) > (y.id, y.f2)

Це дійсно круто, але які б випадки використання для цього були?
mangoПрипив

Це може бути корисно для пошуку всіх записів, які перевищують заданий запис.
Фантюс

2

mysqlsla - один із дуже часто використовуваних інструментів аналізу журналів повільних запитів. Ви можете бачити топ-10 найважливіших запитів з часу останнього розгортання повільних журналів запитів. Він також може сказати вам, скільки разів було запущено запит BAD та скільки загального часу на сервері.


2

Насправді задокументовано , але дуже дратує: автоматичні перетворення на неправильні дати та інше неправильне введення.

Перед MySQL 5.0.2, MySQL прощає незаконні або неправильні значення даних і примушує їх до законних значень для введення даних. У MySQL 5.0.2 і новіших версій це залишається поведінкою за замовчуванням, але ви можете змінити режим SQL сервера, щоб вибрати більш традиційне трактування поганих значень, таким чином, щоб сервер їх відкидав і скасовував заяву, в якій вони виникають.

Що стосується дат: іноді вам пощастить, коли MySQL не налаштовує вхід до дійсних дат поблизу, а натомість зберігає їх як такі, 0000-00-00що за визначенням недійсні. Однак навіть тоді ви могли б хотіти, щоб MySQL вийшов з ладу, а не мовчки зберігав це значення для вас.



1

InnoDB за замовчуванням зберігає всі таблиці в одному глобальному просторі таблиць, які ніколи не скорочуються .

Ви можете використовувати, innodb_file_per_tableякий буде розміщувати кожну таблицю в окремому просторі таблиць, яке буде видалено при видаленні таблиці або бази даних.

Плануйте заздалегідь це, оскільки вам доведеться скинути і відновити базу даних, щоб повернути простір в іншому випадку.

Використання просторів таблиць таблиць


1

Якщо ви вставите в стовпець датаметрі значення порожнього рядка "", MySQL збереже значення як 00/00/0000 00:00:00. На відміну від Oracle, який збереже нульове значення.


1

Під час моїх орієнтирів із великими наборами даних та полями DATETIME цей запит завжди повільніше:

SELECT * FROM mytable
WHERE date(date_colum) BETWEEN '2011-01-01' AND ''2011-03-03';

Чим цей підхід:

SELECT * FROM mytable
WHERE date_column BETWEEN '2011-01-01 00:00:00' AND '2011-03-03 23:59:59'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.