MySQL'in Gizli Özellikleri


101

Yıllardır Microsoft SQL Server ile çalışıyorum, ancak yakın zamanda MySQL'i web uygulamalarımla kullanmaya başladım ve bilgiye açım.

Uzun "gizli özellik" soruları ile devam etmek için , MySQL'in bu açık kaynak veritabanı hakkındaki bilgimi artıracağını umduğum tüm gizli veya kullanışlı özelliklerini bilmek istiyorum.

Yanıtlar:


161

Ödül koyduğuna göre, zor kazanılan sırlarımı paylaşacağım ...

Genel olarak, bugün ayarladığım tüm SQL'lerin alt sorguları kullanması gerekiyordu. Oracle veritabanı dünyasından geldiğim için, kabul ettiğim şeyler MySQL ile aynı şekilde çalışmıyordu. Ve MySQL ayarlamasını okumam, sorguları optimize etme açısından MySQL'in Oracle'ın arkasında olduğu sonucuna varmamı sağlıyor.

Çoğu B2C uygulaması için gerekli olan basit sorgular MySQL için iyi çalışabilirken, Intelligence Reporting için gereken toplu raporlama türlerinin çoğu, MySQL'in onları daha hızlı yürütmesine rehberlik etmek için SQL sorgularını biraz planlama ve yeniden düzenleme gerektiriyor gibi görünüyor.

Yönetim:

max_connectionseşzamanlı bağlantıların sayısıdır. Varsayılan değer 100 bağlantıdır (5.0'dan beri 151) - çok küçük.

Not:

bağlantılar hafızayı alır ve işletim sisteminiz çok fazla bağlantıyı işleyemeyebilir.

Linux / x86 için MySQL ikili dosyaları, 4096 adede kadar eşzamanlı bağlantıya sahip olmanıza izin verir, ancak kendi kendine derlenen ikili dosyalar genellikle daha az sınırlıdır.

Table_cache'yi açık tablolarınızın ve eşzamanlı bağlantılarınızın sayısıyla eşleşecek şekilde ayarlayın. Open_tables değerini izleyin ve eğer hızla büyüyorsa boyutunu büyütmeniz gerekecektir.

Not:

Önceki 2 parametre çok sayıda açık dosya gerektirebilir. 20 + max_connections + table_cache * 2, ihtiyacınız olan şey için iyi bir tahmindir. Linux'ta MySQL'in open_file_limit seçeneği vardır, bu limiti ayarlayın.

Karmaşık sorgularınız varsa sort_buffer_size ve tmp_table_size büyük olasılıkla çok önemlidir. Değerler, sorgunun karmaşıklığına ve mevcut kaynaklara bağlı olacaktır, ancak sırasıyla 4Mb ve 32Mb önerilen başlangıç ​​noktalarıdır.

Not: Bunlar read_buffer_size, read_rnd_buffer_size ve diğerleri arasında "bağlantı başına" değerlerdir, yani bu değer her bağlantı için gerekli olabilir. Bu nedenle, bu parametreleri ayarlarken yükünüzü ve mevcut kaynağınızı göz önünde bulundurun. Örneğin, sort_buffer_size yalnızca MySQL'in bir sıralama yapması gerekiyorsa tahsis edilir. Not: Hafızanın bitmemesine dikkat edin.

Çok sayıda bağlantı kurduysanız (yani kalıcı bağlantıların olmadığı bir web sitesi), thread_cache_size değerini sıfır olmayan bir değere ayarlayarak performansı artırabilirsiniz. 16 ile başlamak iyi bir değerdir. Thread_created çok hızlı büyümeyene kadar değeri artırın.

BİRİNCİL ANAHTAR:

Tablo başına yalnızca bir AUTO_INCREMENT sütunu olabilir, dizine alınmalıdır ve VARSAYILAN bir değere sahip olamaz

KEY normalde INDEX ile eşanlamlıdır. PRIMARY KEY anahtar özelliği, bir sütun tanımında verildiğinde sadece KEY olarak da belirtilebilir. Bu, diğer veritabanı sistemleriyle uyumluluk için uygulanmıştır.

BİRİNCİL ANAHTAR, tüm anahtar sütunlarının NOT NULL olarak tanımlanması gereken benzersiz bir dizindir.

PRIMARY KEY veya UNIQUE indeksi, tamsayı türüne sahip yalnızca bir sütundan oluşuyorsa, SELECT deyimlerinde sütuna "_rowid" olarak da başvurabilirsiniz.

MySQL'de, BİR İLK ANAHTAR'ın adı BİRİNCİL'dir

Şu anda, yalnızca InnoDB (v5.1?) Tabloları yabancı anahtarları desteklemektedir.

Genellikle, tablo oluştururken ihtiyacınız olan tüm dizinleri oluşturursunuz. PRIMARY KEY, KEY, UNIQUE veya INDEX olarak bildirilen herhangi bir sütun indekslenecektir.

NULL, "bir değere sahip olmama" anlamına gelir. NULL testi için, can not örneğin, = aritmetik karşılaştırma operatörlerini kullanın <veya <>. Bunun yerine IS NULL ve IS NOT NULL operatörlerini kullanın:

NO_AUTO_VALUE_ON_ZERO, 0 için otomatik artışı bastırır, böylece sadece NULL sonraki sıra numarasını üretir. Bu mod, bir tablonun AUTO_INCREMENT sütununda 0 depolanmışsa yararlı olabilir. (Bu arada, 0'ı saklamak tavsiye edilen bir uygulama değildir.)

Yeni satırlarda kullanılacak AUTO_INCREMENT sayacının değerini değiştirmek için:

ALTER TABLE mytable AUTO_INCREMENT = value; 

veya SET INSERT_ID = değer;

Aksi belirtilmedikçe, değer 1000000 ile başlar veya şu şekilde belirtir:

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

TIMESTAMPS:

TIMESTAMP sütunlarının değerleri, depolama için geçerli saat diliminden UTC'ye ve alma için UTC'den geçerli saat dilimine dönüştürülür.

http://dev.mysql.com/doc/refman/5.1/en/timestamp.html Bir tablodaki bir TIMESTAMP sütunu için geçerli zaman damgasını varsayılan değer ve otomatik güncelleme değeri olarak atayabilirsiniz.

WHERE yan tümcesinde bu türlerden birini kullanırken dikkat edilmesi gereken bir nokta, WHERE UNIX_TIMESTAMP (datecolumn) = 1057941242 yerine WHERE datecolumn = FROM_UNIXTIME (1057941242) yapmak en iyisidir. ikincisini yapmak bir dizinden yararlanmaz o sütunda.

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

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

MySQL'de bir tarih-
saati unix zaman damgasına dönüştürürseniz: Ve sonra ona 24 saat ekleyin:
Ve sonra onu bir tarih saatine geri dönüştürürseniz sihirli bir şekilde bir saat kaybeder!

İşte neler oluyor. Unix zaman damgasını bir tarih saatine geri dönüştürürken zaman dilimi dikkate alınır ve tam da 28-29 Ekim 2006 arasında yaz saati uygulamasından çıkıp bir saat kaybettik.

MySQL 4.1.3 ile başlayarak, CURRENT_TIMESTAMP (), CURRENT_TIME (), CURRENT_DATE () ve FROM_UNIXTIME () işlevleri, time_zone sistem değişkeninin değeri olarak kullanılabilen, bağlantının geçerli saat dilimindeki değerleri döndürür . Ek olarak, UNIX_TIMESTAMP () bağımsız değişkeninin geçerli saat dilimindeki bir tarih saat değeri olduğunu varsayar.

Geçerli saat dilimi ayarı, UTC_TIMESTAMP () gibi işlevler tarafından görüntülenen değerleri veya DATE, TIME veya DATETIME sütunlarındaki değerleri etkilemez.

NOT: YALNIZCA GÜNCELLEME , bir alan değiştirilirse DateTime'ı günceller Eğer bir GÜNCELLEME hiçbir alanın değiştirilmesine neden olmazsa, DateTime GÜNCELLEMEZ!

Ek olarak, İlk TIMESTAMP belirtilmemiş olsa bile varsayılan olarak her zaman AUTOUPDATE şeklindedir.

Dates ile çalışırken, neredeyse her zaman Julian Date'i kabul ediyorum çünkü Veri matematiği tamsayıları eklemek veya çıkarmak için basit bir mesele ve Midnight beri aynı nedenden dolayı Saniyeler. Saniyelerden daha ince ayrıntıya sahip bir zaman çözümüne ihtiyaç duyduğum nadirdir.

Bunların her ikisi de 4 baytlık bir tamsayı olarak depolanabilir ve boşluk gerçekten dar ise, işaretsiz bir tamsayı olarak UNIX zamanıyla birleştirilebilir (1/1/1970 döneminden bu yana saniyeler), bu yaklaşık 2106'ya kadar iyi olacaktır:

24 saat içinde saniye = 86400

'Signed Integer max val = 2.147.483.647 - 68 yıllık Saniyeyi tutabilir

İşaretsiz Tamsayı maks. Değer = 4,294,967,295 - 136 yıl Saniye tutabilir

İkili Protokol:

MySQL 4.1, dize olmayan veri değerlerinin dize biçimine dönüştürülmeden yerel biçimde gönderilmesine ve döndürülmesine izin veren bir ikili protokol tanıttı. (Çok kullanışlı)

Ayrıca mysql_real_query (), mysql_query () 'den daha hızlıdır çünkü ifade dizgisi üzerinde çalışmak için strlen ()' i çağırmaz.

http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html İkili protokol, sunucu tarafında hazırlanmış ifadeleri destekler ve veri değerlerinin yerel formatta iletilmesine izin verir. İkili protokol, MySQL 4.1'in önceki sürümlerinde epeyce revizyondan geçti.

Bir alanın sayısal bir türü olup olmadığını test etmek için IS_NUM () makrosunu kullanabilirsiniz. Tür değerini IS_NUM () 'a iletin ve alan sayısal ise DOĞRU olarak değerlendirilir:

Nota bir şey ikili veri olmasıdır CAN bunu kaçmak ve MySQL gerektirir hatırlamıyorsam düzenli sorgusu içinde gönderilecek yalnızca ters eğik çizgi ve tırnak karakteri öncelenmelidir söyledi. Bu, örneğin şifreli / Tuzlu parolalar gibi daha kısa ikili dizeleri EKLEMENİN gerçekten kolay bir yoludur.

Ana Sunucu:

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

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

HİBE REPLİKASYONU BAĞLI . slave_user 'slave_password' TARAFINDAN TANIMLANAN

#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

İkili Günlük Dosyası şöyle olmalıdır:

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/en/mysqlbinlog.html

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

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

RESET MASTER deyimi ile tüm ikili günlük dosyalarını veya PURGE MASTER ile bunların bir alt kümesini silebilirsiniz.

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

Normalleştirme:

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

UDF işlevleri

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

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

Veri tipleri:

http://dev.mysql.com/doc/refman/5.1/en/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/

Unutulmaması gereken bir nokta, hem CHAR hem de VARCHAR içeren karma bir tabloda mySQL'in CHAR'ları VARCHAR'lara değiştireceğidir.

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

MySQL, standart SQL ve ISO 8601 spesifikasyonlarına uygun olarak tarihleri ​​her zaman ilk yılla temsil eder

Çeşitli:

Bazı MySQl işlevlerini kapatmak, daha küçük veri dosyalarına ve daha hızlı erişime neden olacaktır. Örneğin:

--datadir veri dizinini belirleyecek ve

--skip-innodb, inno seçeneğini kapatacak ve size 10-20 milyon tasarruf sağlayacaktır

Daha fazla bilgi için http://dev.mysql.com/tech-resources/articles/mysql-c-api.html

Bölüm 7'yi İndir - Ücretsiz

InnoDB işlemseldir, ancak onunla birlikte gelen bir performans yükü vardır. MyISAM tablolarımın% 90'ı için yeterli buldum. İşlem güvenli olmayan tabloların (MyISAM) çeşitli avantajları vardır ve bunların tümü aşağıdaki nedenlerle oluşur:

işlem ek yükü yoktur:

Çok daha hızlı

Daha düşük disk alanı gereksinimleri

Güncellemeleri gerçekleştirmek için daha az bellek gerekir

Her MyISAM tablosu diskte üç dosyada saklanır. Dosyaların tablo adıyla başlayan ve dosya türünü belirtmek için bir uzantıya sahip adları vardır. Bir .frm dosyası, tablo biçimini depolar. Veri dosyası .MYD (MYData) uzantısına sahiptir. Dizin dosyası .MYI (MYIndex) uzantısına sahiptir.

Bunlar Dosyalar olabilir zaman alıcı (böyledir Restore) 'dir MySQL Yöneticiler Yedekleme özelliği kullanmadan bozulmamış bir depolama konumuna kopyalanabilir

İşin püf noktası, bu dosyaların bir kopyasını oluşturmak ve ardından tabloyu BIRAKMAK. Dosyaları geri koyduğunuzda MySQl onları tanıyacak ve tablo takibini güncelleyecektir.

Yedeklemeniz / Geri Yüklemeniz gerekiyorsa,

Bir yedeği geri yüklemek veya mevcut bir döküm dosyasından içe aktarmak, her tablodaki dizinlerin ve birincil anahtarlarınızın sayısına bağlı olarak uzun sürebilir. Orijinal döküm dosyanızı aşağıdakilerle çevreleyerek değiştirerek bu işlemi önemli ölçüde hızlandırabilirsiniz:

SET AUTOCOMMIT = 0;
SET FOREIGN_KEY_CHECKS=0;

.. your dump file ..

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

Yeniden yükleme hızını büyük ölçüde artırmak için SET AUTOCOMMIT = 0 SQL komutunu ekleyin; döküm dosyasının başında ve COMMIT'i ekleyin; sonuna kadar komut.

Varsayılan olarak, autocommit açıktır, yani döküm dosyasındaki her bir ekleme komutu ayrı bir işlem olarak değerlendirilir ve bir sonraki başlatılmadan önce diske yazılır. Bu komutları eklemezseniz, büyük bir veritabanını InnoDB'ye yeniden yüklemek saatler sürebilir ...

Bir MySQL tablosundaki bir satırın maksimum boyutu 65.535 bayttır

MySQL 5.0.3'te bir VARCHAR'ın etkin maksimum uzunluğu ve on = maksimum satır boyutu (65.535 bayt)

VARCHAR değerleri depolandıklarında doldurulmaz. Takip eden boşluklar, standart SQL ile uyumlu olarak değerler depolandığında ve alındığında korunur.

MySQL'deki CHAR ve VARCHAR değerleri, sondaki boşluklara bakılmaksızın karşılaştırılır.

CHAR kullanmak, yalnızca tüm kayıt sabit boyutta ise erişiminizi hızlandıracaktır. Yani, herhangi bir değişken boyutlu nesne kullanırsanız, hepsini de değişken boyutlu yapabilirsiniz. Bir VARCHAR içeren bir tabloda CHAR kullanarak hız kazanmazsınız.

255 karakterlik VARCHAR sınırı MySQL 5.0.3 itibarıyla 65535 karaktere çıkarıldı.

Tam metin aramaları yalnızca MyISAM tabloları için desteklenir.

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

BLOB sütunlarının karakter kümesi yoktur ve sıralama ve karşılaştırma, sütun değerlerindeki baytların sayısal değerlerine dayanır

Katı SQL modu etkin değilse ve bir BLOB veya TEXT sütununa, sütunun maksimum uzunluğunu aşan bir değer atarsanız, değer sığması için kesilir ve bir uyarı oluşturulur.

Yararlı Komutlar:

katı modu kontrol edin: SELECT @@ global.sql_mode;

katı modu kapat:

SET @@ global.sql_mode = '';

SET @@ global.sql_mode = 'MYSQL40'

veya kaldır: sql-mode = "STRICT_TRANS_TABLES, ...

SÜTUNLARI GÖSTER mytable

Mytable virtualcolumnSİPARİŞİNİN sanal sütuna göre SİPARİŞİNDEN maks (ad sayısı) SEÇİN

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

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

size mevcut iş parçacığına eklenen son satırın PK'sini verir max (pkcolname) genel olarak son PK'yi verir.

Not: Eğer tablo boşsa max (pkcolname) 1 döndürür mysql_insert_id (), yerel MySQL C API işlevinin dönüş türünü mysql_insert_id () bir long türüne (PHP'de int olarak adlandırılır) dönüştürür.

AUTO_INCREMENT sütununuzda BIGINT sütun türü varsa, mysql_insert_id () tarafından döndürülen değer yanlış olacaktır. Bunun yerine, bir SQL sorgusunda dahili MySQL SQL işlevi LAST_INSERT_ID () kullanın.

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

Bir tabloya veri eklemeye çalışırken hatayı aldığınızı unutmayın:

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

gibi bir şey kullanmak

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

Bunun nedeni, tabloya yapıştırmaya çalıştığınız değerlerin etrafında kesme işaretinin olmamasıdır. Bu nedenle kodunuzu şu şekilde değiştirmelisiniz:

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

`` değerleri değil, MySQL alanlarını, veritabanlarını veya tablolarını tanımlamak için kullanılır;)

Sorgu sırasında sunucuyla bağlantı kesildi:

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

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

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

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

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

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

Sorguları Ayarlama

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

Bence bu bonusu kazanmak için yeterli olmalı ... Harika bir ücretsiz veritabanı ile birçok saatin ve birçok projenin meyveleri . Uygulama veri sunucularını Windows platformlarında çoğunlukla MySQL ile geliştiriyorum. Düzeltmem gereken en kötü karışıklık

Eski MySQL veritabanı kabusu

Bu, tabloları burada bahsedilen birçok püf noktasını kullanarak faydalı bir hale dönüştürmek için bir dizi uygulama gerektiriyordu.

Bunu şaşırtıcı derecede yararlı bulduysanız, oy vererek teşekkürlerinizi ifade edin.

Ayrıca diğer makalelerime ve teknik incelemelerime şu adresten bakın: www.coastrd.com


22

MySQL kadar gizli değil özelliğinin bu SQL uyumlu konusunda oldukça iyi değil yani, iyi değil, hatalar gerçekten ama, daha FRİKİKLERİNDEN ... :-)


Diğer mektuplar, bu listenin MSSQL'den MySQL'e geçerken değerli olduğunu bilir. Şerefe Mat.
GateKiller

Bu sorunların çoğu MySQL'in önceki sürümlerindendir.
jmucchiello

birincisi, zaman damgası alanına NULL değeri koymanın mümkün olacağını sanmıyorum.
mat

3
MySQL, SQL uyumlu olma konusunda diğer birçok veritabanından daha kötü değildir; SQL'in mantıklı bir alt kümesine sadık kaldığınız sürece, genellikle sorunlardan kaçınabilirsiniz - bu, örneğin, söylenebileceğinden daha fazlasıdır. Oracle'ın rezil NULL boş dizeleri.
bobince

1
Bazı sorunları devre dışı bırakabilirsinizSET SESSION sql_mode='ANSI';
Kornel

21

Önbellekte o anda hangi tabloların bulunduğunu bulmak için bir komut:

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

( MySQL performans blogundan )


15

Kimin ne yaptığını bulma komutu:

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) 

Ve bir süreci şu şekilde öldürebilirsiniz:

mysql>kill 5 

5
ayrıca sorguların kesilmesini istemiyorsanız TAM İŞLEM LİSTESİ GÖSTERİN.
Greg

11

Özellikle MySQL'in inet_ntoa()ve için yerleşik desteğini seviyorum inet_aton(). Tablolardaki IP adreslerinin işlenmesini çok kolay hale getirir (en azından sadece IPv4 adresleri oldukları sürece!)


2
PostgreSQL, ipv4 ve ipv6'yı çok güzel işleyen çok güzel bir inet türüne sahiptir :-)
mat

Ben de severdim ama onları hiç kullanmamak daha da iyi. Postgres için +1.
Kornel

11

on duplicate keyTembel oluşturulmuş her türlü sayaç için seviyorum (AKA yükselt, birleştirme)

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

Bir sorguya birçok satır ekleyebilir ve her satır için yinelenen dizini hemen işleyebilirsiniz.


10

Yine - gerçekten gizli özellikler değil, ama gerçekten kullanışlı:

Özellik

DDL'yi kolayca yakalayın:

SHOW CREATE TABLE CountryLanguage

çıktı:

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

Özellik: GROUP_CONCAT () toplama işlevi Ayrıntı başına argümanlarının birleştirilmiş bir dizesini oluşturur ve bunları grup başına birleştirerek toplar.

Örnek 1: basit

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

Çıktı:

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

Örnek 2: birden çok bağımsız değişken

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

Çıktı:

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

Örnek 3: Özel bir ayırıcı kullanma

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

Çıktı:

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

Örnek 4: Liste öğelerinin sırasını kontrol etme

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

Çıktı:

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

Özellik: COUNT (DISTINCT) birden çok ifade ile

Kombinasyonların sayısını saymak için bir COUNT (DISTINCT ...) ifadesinde birden çok ifade kullanabilirsiniz.

SELECT COUNT(DISTINCT CountryCode, Language) FROM CountryLanguage

Özellik / Gotcha: GROUP BY listesine toplu olmayan ifadeleri eklemenize gerek yok

Çoğu RDBMS, SELECT listesindeki tüm toplanmamış ifadelerin GROUP BY'da görünmesini gerektiren SQL92 uyumlu bir GROUP BY uygular. Bu RDBMS'lerde şu ifade:

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

geçerli değil, çünkü SEÇİM listesi, GRUPLARA GÖRE listesinde görünmeyen toplanmamış Country.Continent sütununu içeriyor. Bu RDBMS'lerde, okumak için GROUP BY listesini değiştirmeniz gerekir.

GROUP BY   Country.Code, Country.Continent

veya Country.Continent'e anlamsız bir toplam eklemelisiniz, örneğin

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

Şimdi, mesele şu ki, mantıksal olarak Country.Continent'in toplanmasını talep eden hiçbir şey yok. Bkz. Ülke Kodu, Ülke tablosunun birincil anahtarıdır. Country.Continent aynı zamanda Country tablosundan bir sütundur ve bu nedenle tanımları gereği fonksiyonel olarak Country.Code birincil anahtarına bağlıdır. Dolayısıyla, her farklı Country.Code için Country.Continent'te tam olarak bir değer bulunmalıdır. Bunu anlarsanız, onu toplamanın (tek bir değer vardır, doğru) veya ona göre gruplamanın (çünkü zaten gruplama yaptığınız için sonucu daha benzersiz yapmayacağından) anlamsız olduğunun farkına varırsınız. pk)

Her neyse - MySQL, onları GROUP BY yan tümcesine eklemenizi gerektirmeden, bir araya getirilmemiş sütunları SELECT listesine eklemenize izin verir.

Bununla ilgili olan şey, toplanmamış bir sütun kullanmanız durumunda MySQL'in sizi korumamasıdır. Öyleyse, şöyle bir sorgu:

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

Şikayet edilmeden yürütülecektir, ancak CountryLanguage.Percentage sütunu anlamsızlık içerecektir (yani, tüm dil yüzdelerinden, yüzde için mevcut değerlerden biri rastgele veya en azından kontrolünüz dışında seçilecektir.

Bakınız: Efsanelere Göre Grubu Debunking


Grup tarafından bildirilmeyen sütunlara izin verilmesi, Oracle'dan gelen en az sevdiğim özelliklerden biridir. Oracle'a alışkınsanız bu büyük bir sorun - sadece sorguyu çalıştırmanıza izin veriyor, sonuçlar doğru görünüyor, ancak daha sonra onun düşündüğünüz şeyi yapmadığını anlıyorsunuz.
mbafford

7

İstemcideki "çağrı cihazı" komutu

Örneğin, sonucunuzda 10.000 satır varsa ve bunları görüntülemek istiyorsanız (Bu, normalde Linux'ta olan "less" ve "tee" komutlarının mevcut olduğunu varsayar; Windows YMMV'de.)

pager less
select lots_of_stuff FROM tbl WHERE clause_which_matches_10k_rows;

Ve onları "daha az" dosya görüntüleyiciye alacaksınız, böylece güzelce sayfalarında gezinebilir, arama yapabilir, vb.

Ayrıca

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

Bir dosyaya rahatlıkla yazacak.


ne yazık ki pencereler altında, "daha az" ve "tee" mevcut olsa bile, çağrı cihazı seçeneğinin kendisi desteklenmez. kolay kolay değil
Berry Tsakala

6

İlginç bulabileceğiniz bazı şeyler:

<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

İşte ipuçlarımdan bazıları - onlar hakkında blogumda blog yazdım ( Link )

  1. Değişkenleri bildirirken '@' işaretini kullanmanıza gerek yoktur.
  2. Bir ifadenin sonunu sınırlamak için bir sınırlayıcı (varsayılan ';') kullanmanız gerekir - Bağlantı
  3. Verileri MS-SQL 2005 ile mySQL arasında taşımaya çalışıyorsanız, atlamak için birkaç çember vardır - Bağlantı
  4. MySQL'de büyük / küçük harfe duyarlı eşleşmeler yapmak - bağlantı


3

Cmdline Mysq kullanıyorsanız, çığlık / ünlem işaretini kullanarak komut satırıyla (Linux makinelerde - Windows'ta eşdeğer bir etki olup olmadığından emin değilsiniz) etkileşime girebilirsiniz. Örneğin:

\! cat file1.sql

file1.sql kodunu gösterecektir. İfadenizi ve sorgunuzu bir dosyaya kaydetmek için tee tesisini kullanın

\T filename

bunu kapatmak için şunu kullan \ t

Son olarak, önceden kaydettiğiniz bir komut dosyasını çalıştırmak için "kaynak dosya adı" kullanın. Tabii ki, normal alternatif, mysql'yi komut satırından başlatırken komut dosyası adına yönlendirmektir:

    mysql -u root -p < case1.sql

Umarım bu birinin işine yarar!

Düzenleme: Sadece bir tane daha hatırladım - komut satırından mysql'i çağırırken -t anahtarını kullanabilirsiniz, böylece çıktı tablo biçiminde olur - bazı sorgularda gerçek bir nimettir (tabii ki burada başka yerlerde bahsedildiği gibi \ G ile sorguları sonlandırmak da) bu açıdan yararlıdır). Çeşitli anahtarlarda çok daha fazlası Komut Satırı Aracı

Bir sıralamanın sırasını değiştirmenin düzgün bir yolunu buldum (normalde Büyük / Küçük Harf kullanın ...) Bir sıralamanın sırasını değiştirmek istiyorsanız (belki 1, 2, 3 yerine 1, 4, 3, 2'ye göre sıralayın, 4) Order by cümlesi içindeki alan işlevini kullanabilirsiniz. Örneğin

Alana Göre Sırala (sort_field, 1,4,3,2)


3

Bunun MySQL'e özgü olduğunu düşünmüyorum, ama benim için aydınlatıcı:

Yazmak yerine

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

Sadece yazabilirsin

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

Bu gerçekten harika ama bunun için bazı kullanım durumları ne olabilir?
mangoDrunk

Belirli bir kayıttan daha büyük olan tüm kayıtları bulmak için yararlı olabilir.
Fantius

2

mysqlsla - Çok yaygın olarak kullanılan yavaş sorgu günlüğü analiz araçlarından biri. Yavaş sorgu günlüklerini son kullanıma sunduğunuzdan bu yana en kötü 10 sorguyu görebilirsiniz. Ayrıca, KÖTÜ sorgunun kaç kez tetiklendiğini ve sunucuda toplam ne kadar süre geçtiğini de söyleyebilir.


2

Gerçekte belgelenmiş , ancak çok can sıkıcı: yanlış tarihler için otomatik dönüştürmeler ve diğer yanlış girişler.

MySQL 5.0.2'den önce, MySQL yasadışı veya uygun olmayan veri değerlerini affeder ve bunları veri girişi için yasal değerlere zorlar. MySQL 5.0.2 ve üzeri sürümlerde, bu varsayılan davranış olarak kalır, ancak sunucu SQL modunu değiştirerek kötü değerlerin daha geleneksel bir şekilde ele alınmasını seçebilirsiniz, böylece sunucu onları reddeder ve oluştukları ifadeyi iptal eder.

Tarihlere gelince: Bazen MySQL girdiyi yakındaki geçerli tarihlere ayarlamadığında, bunun yerine 0000-00-00tanım gereği geçersiz olanı olarak sakladığında "şanslı" olursunuz . Ancak, o zaman bile, bu değeri sizin için sessizce depolamak yerine MySQL'in başarısız olmasını isteyebilirsiniz.



1

InnoDB varsayılan olarak tüm tabloları asla küçülmeyecek tek bir genel tablo alanında depolar .

innodb_file_per_tableTabloyu veya veritabanını bıraktığınızda silinecek olan her tabloyu ayrı bir tablo alanına yerleştirecek olanı kullanabilirsiniz .

Aksi takdirde alan kazanmak için veritabanını boşaltmanız ve geri yüklemeniz gerektiğinden bunun için önceden plan yapın.

Tablo Başına Tablo Alanlarını Kullanma


1

Tarih saat sütununa boş dize değeri "" eklerseniz, MySQL değeri 00/00/0000 00:00:00 olarak tutacaktır. Oracle'dan farklı olarak, boş değerden tasarruf edecek.


1

Büyük veri kümelerine ve DATETIME alanlarına sahip karşılaştırmalarım sırasında, bu sorguyu yapmak her zaman daha yavaştır:

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

Bu yaklaşımdan daha fazlası:

SELECT * FROM mytable
WHERE date_column BETWEEN '2011-01-01 00:00:00' AND '2011-03-03 23:59:59'
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.