Fitur Tersembunyi MySQL

101

Saya telah bekerja dengan Microsoft SQL Server selama bertahun-tahun sekarang tetapi baru saja mulai menggunakan MySQL dengan aplikasi web saya, dan saya haus akan pengetahuan.

Untuk melanjutkan pertanyaan panjang "fitur tersembunyi" , saya ingin mengetahui fitur tersembunyi atau berguna dari MySQL yang diharapkan dapat meningkatkan pengetahuan saya tentang database open source ini.

GateKiller
sumber

Jawaban:

161

Karena Anda memberikan hadiah, saya akan membagikan rahasia saya dengan susah payah ...

Secara umum, semua SQL yang saya setel hari ini diperlukan menggunakan sub-kueri. Berasal dari dunia database Oracle, hal-hal yang saya anggap remeh tidak berfungsi sama dengan MySQL. Dan bacaan saya tentang penyetelan MySQL membuat saya menyimpulkan bahwa MySQL berada di belakang Oracle dalam hal mengoptimalkan kueri.

Meskipun kueri sederhana yang diperlukan untuk sebagian besar aplikasi B2C dapat berfungsi dengan baik untuk MySQL, sebagian besar jenis kueri pelaporan agregat yang diperlukan untuk Intelligence Reporting tampaknya memerlukan sedikit perencanaan dan pengaturan ulang kueri SQL untuk memandu MySQL agar dapat mengeksekusinya lebih cepat.

Administrasi:

max_connectionsadalah jumlah koneksi serentak. Nilai defaultnya adalah 100 koneksi (151 sejak 5.0) - sangat kecil.

catatan:

koneksi membutuhkan memori dan OS Anda mungkin tidak dapat menangani banyak koneksi.

Biner MySQL untuk Linux / x86 memungkinkan Anda memiliki hingga 4096 koneksi bersamaan, tetapi biner yang dikompilasi sendiri sering kali memiliki lebih sedikit batas.

Setel table_cache agar sesuai dengan jumlah tabel terbuka dan koneksi serentak Anda. Perhatikan nilai open_tables dan jika itu berkembang dengan cepat Anda perlu meningkatkan ukurannya.

catatan:

2 parameter sebelumnya mungkin membutuhkan banyak file yang terbuka. 20 + max_connections + table_cache * 2 adalah perkiraan yang baik untuk apa yang Anda butuhkan. MySQL di Linux memiliki opsi open_file_limit, setel batas ini.

Jika Anda memiliki kueri kompleks, sort_buffer_size dan tmp_table_size sepertinya sangat penting. Nilai akan bergantung pada kompleksitas kueri dan sumber daya yang tersedia, tetapi 4Mb dan 32Mb, masing-masing adalah titik awal yang direkomendasikan.

Catatan: Ini adalah nilai "per koneksi", antara read_buffer_size, read_rnd_buffer_size dan beberapa lainnya, yang berarti bahwa nilai ini mungkin diperlukan untuk setiap koneksi. Jadi, pertimbangkan beban Anda dan sumber daya yang tersedia saat menyetel parameter ini. Misalnya sort_buffer_size dialokasikan hanya jika MySQL perlu melakukan sortir. Catatan: hati-hati jangan sampai kehabisan memori.

Jika Anda memiliki banyak koneksi yang dibuat (yaitu situs web tanpa koneksi tetap), Anda dapat meningkatkan kinerja dengan menyetel thread_cache_size ke nilai bukan nol. 16 adalah nilai yang bagus untuk memulai. Tingkatkan nilainya sampai threads_created Anda tidak tumbuh dengan sangat cepat.

KUNCI UTAMA:

Hanya boleh ada satu kolom AUTO_INCREMENT per tabel, itu harus diindeks, dan tidak boleh memiliki nilai DEFAULT

KEY biasanya merupakan sinonim untuk INDEX. Atribut kunci PRIMARY KEY juga dapat ditentukan hanya sebagai KEY ketika diberikan dalam definisi kolom. Ini diimplementasikan untuk kompatibilitas dengan sistem database lain.

A PRIMARY KEY adalah indeks unik di mana semua kolom kunci harus didefinisikan sebagai NOT NULL

Jika PRIMARY KEY atau UNIQUE index hanya terdiri dari satu kolom yang memiliki tipe integer, Anda juga dapat merujuk ke kolom tersebut sebagai "_rowid" dalam pernyataan SELECT.

Di MySQL, nama PRIMARY KEY adalah PRIMARY

Saat ini, hanya tabel InnoDB (v5.1?) Yang mendukung kunci asing.

Biasanya, Anda membuat semua indeks yang Anda butuhkan saat membuat tabel. Setiap kolom yang dideklarasikan sebagai PRIMARY KEY, KEY, UNIQUE, atau INDEX akan diindeks.

NULL berarti "tidak memiliki nilai". Untuk menguji NULL, Anda tidak dapat menggunakan operator perbandingan aritmatika seperti =, <, atau <>. Gunakan operator IS NULL dan IS NOT NULL sebagai gantinya:

NO_AUTO_VALUE_ON_ZERO menekan kenaikan otomatis untuk 0 sehingga hanya NULL yang menghasilkan nomor urut berikutnya. Mode ini bisa berguna jika 0 telah disimpan di kolom AUTO_INCREMENT tabel. (Ngomong-ngomong, menyimpan 0 bukanlah praktik yang disarankan.)

Untuk mengubah nilai penghitung AUTO_INCREMENT yang akan digunakan untuk baris baru:

ALTER TABLE mytable AUTO_INCREMENT = value; 

atau SET INSERT_ID = value;

Kecuali ditentukan lain, nilainya akan dimulai dengan: 1000000 atau ditetapkan sebagai:

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

TIMESTAMPS:

Nilai untuk kolom TIMESTAMP diubah dari zona waktu saat ini ke UTC untuk penyimpanan, dan dari UTC ke zona waktu saat ini untuk pengambilan.

http://dev.mysql.com/doc/refman/5.1/en/timestamp.html Untuk satu kolom TIMESTAMP dalam tabel, Anda dapat menetapkan stempel waktu saat ini sebagai nilai default dan nilai pembaruan otomatis.

satu hal yang harus diperhatikan saat menggunakan salah satu dari jenis ini dalam klausa WHERE, yang terbaik adalah melakukan WHERE datecolumn = FROM_UNIXTIME (1057941242) dan bukan WHERE UNIX_TIMESTAMP (datecolumn) = 1057941242. melakukan yang terakhir tidak akan memanfaatkan indeks di kolom itu.

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

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

jika Anda mengonversi datetime menjadi unix timestamp di MySQL:
Dan kemudian menambahkan 24 jam ke dalamnya:
Dan kemudian mengubahnya kembali ke datetime secara ajaib kehilangan satu jam!

Inilah yang terjadi. Ketika mengubah stempel waktu unix kembali ke datetime zona waktu dipertimbangkan dan kebetulan antara 28 dan 29 Oktober 2006 kami kehilangan waktu musim panas dan kehilangan satu jam.

Dimulai dengan MySQL 4.1.3, fungsi CURRENT_TIMESTAMP (), CURRENT_TIME (), CURRENT_DATE (), dan FROM_UNIXTIME () mengembalikan nilai dalam zona waktu koneksi saat ini , yang tersedia sebagai nilai variabel sistem zona waktu . Selain itu, UNIX_TIMESTAMP () mengasumsikan bahwa argumennya adalah nilai datetime di zona waktu saat ini.

Pengaturan zona waktu saat ini tidak mempengaruhi nilai yang ditampilkan oleh fungsi seperti UTC_TIMESTAMP () atau nilai dalam kolom DATE, TIME, atau DATETIME.

CATATAN: ON UPDATE ONLY memperbarui DateTime jika bidang diubah Jika UPDATE tidak menghasilkan bidang yang diubah, maka DateTime TIDAK diperbarui!

Sebagai tambahan, TIMESTAMP Pertama selalu AUTOUPDATE secara default meskipun tidak ditentukan

Ketika bekerja dengan Tanggal, saya hampir selalu menggantungkan pada Tanggal Julian karena Data matematika kemudian merupakan masalah sederhana menambahkan atau subtracing bilangan bulat, dan Detik sejak Tengah Malam untuk alasan yang sama. Jarang saya membutuhkan waktu untuk menghasilkan perincian yang lebih halus daripada detik.

Keduanya dapat disimpan sebagai integer 4 byte, dan jika spasi sangat sempit dapat digabungkan ke dalam waktu UNIX (detik sejak epoch 1/1/1970) sebagai integer yang tidak bertanda tangan yang akan baik hingga sekitar 2106 sebagai:

detik dalam 24 Jam = 86400

'Signed Integer max val = 2.147.483.647 - dapat menampung 68 tahun Detik

'Unsigned Integer max val = 4.294.967.295 - dapat menampung 136 tahun Detik

Protokol Biner:

MySQL 4.1 memperkenalkan protokol biner yang memungkinkan nilai data non-string dikirim dan dikembalikan dalam format asli tanpa konversi ke dan dari format string. (Sangat berguna)

Selain itu, mysql_real_query () lebih cepat daripada mysql_query () karena tidak memanggil strlen () untuk beroperasi pada string pernyataan.

http://dev.mysql.com/tech-resources/articles/4.1/prepared-statements.html Protokol biner mendukung pernyataan yang disiapkan sisi server dan memungkinkan transmisi nilai data dalam format asli. Protokol biner mengalami sedikit revisi selama rilis MySQL 4.1 sebelumnya.

Anda dapat menggunakan makro IS_NUM () untuk menguji apakah bidang memiliki tipe numerik. Teruskan nilai type ke IS_NUM () dan nilai tersebut dievaluasi TRUE jika bidangnya numerik:

Satu hal yang perlu diperhatikan adalah bahwa data biner DAPAT dikirim di dalam kueri biasa jika Anda menghindarinya dan ingat MySQL hanya memerlukan garis miring terbalik dan karakter kutipan yang akan di-escape. Jadi itu adalah cara yang sangat mudah untuk MEMASUKKAN string biner yang lebih pendek seperti kata sandi yang dienkripsi / Salted misalnya.

Server Utama:

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

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

HIBAHKAN REPLIKASI . ke slave_user DIIDENTIFIKASI OLEH '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

File Log Biner harus membaca:

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

Anda dapat menghapus semua file log biner dengan pernyataan RESET MASTER, atau sebagian dari mereka dengan PURGE MASTER

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

Normalisasi:

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

Fungsi UDF

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

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

Tipe Data:

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/

Satu hal yang perlu diperhatikan adalah bahwa pada tabel campuran dengan CHAR dan VARCHAR, mySQL akan mengubah CHAR menjadi VARCHAR.

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

MySQL selalu merepresentasikan tanggal dengan tahun pertama, sesuai dengan standar SQL dan spesifikasi ISO 8601

Lain-lain:

Menonaktifkan beberapa fungsi MySQl akan menghasilkan file data yang lebih kecil dan akses yang lebih cepat. Sebagai contoh:

--datadir akan menentukan direktori data dan

--skip-innodb akan mematikan opsi inno dan menghemat 10-20M

Selengkapnya di sini http://dev.mysql.com/tech-resources/articles/mysql-c-api.html

Unduh Bab 7 - Gratis

InnoDB bersifat transaksional tetapi ada overhead kinerja yang menyertainya. Saya merasa tabel MyISAM cukup untuk 90% proyek saya. Tabel non-transaksi-aman (MyISAM) memiliki beberapa keunggulannya sendiri, yang semuanya terjadi karena:

tidak ada overhead transaksi:

Lebih cepat

Persyaratan ruang disk yang lebih rendah

Lebih sedikit memori yang dibutuhkan untuk melakukan pembaruan

Setiap tabel MyISAM disimpan di disk dalam tiga file. File memiliki nama yang dimulai dengan nama tabel dan memiliki ekstensi untuk menunjukkan jenis file. File .frm menyimpan format tabel. File data memiliki ekstensi .MYD (MYData). File indeks memiliki ekstensi .MYI (MYIndex).

File-file ini dapat disalin ke lokasi penyimpanan secara utuh tanpa menggunakan fitur Cadangan Administrator MySQL yang memakan waktu (begitu juga Pemulihan)

Caranya adalah membuat salinan dari file-file ini kemudian DROP tabelnya. Saat Anda mengembalikan file, MySQl akan mengenalinya dan memperbarui tabel pelacakan.

Jika Anda harus Backup / Restore,

Memulihkan cadangan, atau mengimpor dari file dump yang ada dapat memakan waktu lama bergantung pada jumlah indeks dan kunci utama yang Anda miliki di setiap tabel. Anda dapat mempercepat proses ini secara dramatis dengan memodifikasi file dump asli Anda dengan mengelilinginya dengan yang berikut:

SET AUTOCOMMIT = 0;
SET FOREIGN_KEY_CHECKS=0;

.. your dump file ..

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

Untuk sangat meningkatkan kecepatan reload, tambahkan perintah SQL SET AUTOCOMMIT = 0; di awal file dump, dan tambahkan COMMIT; perintah sampai akhir.

Secara default, autocommit aktif, artinya setiap perintah penyisipan dalam file dump akan diperlakukan sebagai transaksi terpisah dan ditulis ke disk sebelum yang berikutnya dimulai. Jika Anda tidak menambahkan perintah ini, memuat ulang database besar ke InnoDB bisa memakan waktu berjam-jam ...

Ukuran maksimum baris dalam tabel MySQL adalah 65.535 byte

Panjang maksimum efektif VARCHAR di MySQL 5.0.3 dan on = ukuran baris maksimum (65.535 byte)

Nilai VARCHAR tidak empuk saat disimpan. Ruang jejak dipertahankan ketika nilai disimpan dan diambil, sesuai dengan SQL standar.

Nilai CHAR dan VARCHAR di MySQL dibandingkan tanpa memperhatikan spasi tambahan.

Menggunakan CHAR hanya akan mempercepat akses Anda jika seluruh record berukuran tetap. Artinya, jika Anda menggunakan objek ukuran variabel, Anda mungkin juga membuat semuanya ukuran variabel. Anda tidak mendapatkan kecepatan dengan menggunakan CHAR dalam tabel yang juga berisi VARCHAR.

Batas VARCHAR 255 karakter dinaikkan menjadi 65535 karakter pada MySQL 5.0.3

Pencarian teks lengkap hanya didukung untuk tabel MyISAM.

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

Kolom BLOB tidak memiliki himpunan karakter, dan pengurutan serta perbandingan didasarkan pada nilai numerik byte dalam nilai kolom

Jika mode SQL ketat tidak diaktifkan dan Anda menetapkan nilai ke kolom BLOB atau TEXT yang melebihi panjang maksimum kolom, nilai tersebut akan dipotong agar pas dan peringatan akan dibuat.

Perintah Berguna:

periksa mode ketat: PILIH @@ global.sql_mode;

matikan mode ketat:

SET @@ global.sql_mode = '';

SET @@ global.sql_mode = 'MYSQL40'

atau hapus: sql-mode = "STRICT_TRANS_TABLES, ...

TAMPILKAN KOLOM DARI mytable

PILIH max (namecount) SEBAGAI virtualcolumnDARI mytable ORDER BY virtualcolumn

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 ()

memberi Anda PK dari baris terakhir yang dimasukkan dalam utas saat ini maks (pkcolname) memberi Anda PK terakhir secara keseluruhan.

Catatan: jika tabel kosong max (pkcolname) mengembalikan 1 mysql_insert_id () mengubah jenis kembali dari fungsi MySQL C API asli mysql_insert_id () menjadi jenis panjang (dinamai int dalam PHP).

Jika kolom AUTO_INCREMENT Anda memiliki tipe kolom BIGINT, nilai yang dikembalikan oleh mysql_insert_id () tidak akan benar. Sebagai gantinya, gunakan fungsi MySQL SQL internal LAST_INSERT_ID () dalam kueri SQL.

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

Perhatikan bahwa ketika Anda mencoba memasukkan data ke dalam tabel dan Anda mendapatkan kesalahan:

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

menggunakan sesuatu seperti

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

itu karena Anda tidak memiliki apostrof di sekitar nilai yang Anda coba tempelkan ke dalam tabel. Jadi, Anda harus mengubah kode Anda menjadi:

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

pengingat bahwa `` digunakan untuk menentukan bidang MySQL, database, atau tabel, bukan nilai;)

Kehilangan koneksi ke server selama kueri:

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

Pertanyaan Penyelarasan

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

Itu seharusnya cukup untuk mendapatkan bonus, saya akan berpikir ... Buah dari berjam-jam dan banyak proyek dengan database gratis yang hebat . Saya mengembangkan server data aplikasi pada platform windows kebanyakan dengan MySQL. Kekacauan terburuk yang harus saya selesaikan adalah

Mimpi buruk pamungkas database MySQL legacy

Ini membutuhkan serangkaian aplikasi untuk memproses tabel menjadi sesuatu yang berguna dengan menggunakan banyak trik yang disebutkan di sini.

Jika menurut Anda ini sangat membantu, ungkapkan terima kasih Anda dengan memberikan suara.

Lihat juga artikel dan kertas putih saya yang lain di: www.coastrd.com

Mike Trader
sumber
22

Salah satu fitur yang tidak begitu tersembunyi dari MySQL adalah bahwa hal itu tidak benar-benar baik di menjadi SQL compliant, baik, tidak bug benar-benar, tapi, lebih gotchas ... :-)

tikar
sumber
Lettings lain tahu bahwa daftar ini sangat berharga ketika pindah dari MSSQL ke MySQL. Cheers Mat.
GateKiller
Banyak dari gotcha tersebut berasal dari versi MySQL sebelumnya.
jmucchiello
untuk satu, saya tidak berpikir itu akan pernah mungkin untuk menempatkan nilai NULL dalam bidang cap waktu.
gelaran
3
MySQL tidak lebih buruk dalam hal memenuhi persyaratan SQL daripada banyak database lainnya; selama Anda tetap berpegang pada subset SQL yang waras, Anda biasanya dapat menghindari gotcha - yang lebih dari yang bisa dikatakan misalnya. String kosong NULL Oracle yang terkenal.
bobince
1
Anda dapat menonaktifkan beberapa gotchaSET SESSION sql_mode='ANSI';
Kornel
21

Perintah untuk mengetahui tabel apa yang saat ini ada di cache:

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

(Dari blog kinerja MySQL )

Eran Galperin
sumber
15

Perintah untuk mengetahui siapa melakukan apa:

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) 

Dan Anda dapat menghentikan proses dengan:

mysql>kill 5 
CMS
sumber
5
juga TUNJUKKAN DAFTAR PROSES LENGKAP jika Anda tidak ingin kueri terpotong.
Greg
11

Saya sangat menyukai dukungan bawaan MySQL untuk inet_ntoa()dan inet_aton(). Itu membuat penanganan alamat IP dalam tabel menjadi sangat mudah (setidaknya selama mereka hanya alamat IPv4!)

Alnitak
sumber
2
PostgreSQL memiliki tipe inet yang sangat bagus, yang menangani ipv4 dan ipv6 dengan sangat baik :-)
mat
Saya dulu menyukainya juga, tetapi tidak harus menggunakannya sama sekali bahkan lebih baik. 1 untuk Postgres.
Kornel
11

Saya suka on duplicate key(AKA upsert, merge) untuk semua jenis penghitung yang dibuat dengan malas:

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

Anda dapat menyisipkan banyak baris dalam satu kueri, dan segera menangani indeks duplikat untuk setiap baris.

porneL
sumber
10

Sekali lagi - bukan fitur yang benar-benar tersembunyi, tetapi sangat berguna:

Fitur

Ambil DDL dengan mudah:

SHOW CREATE TABLE CountryLanguage

keluaran:

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

Fitur: Fungsi agregat GROUP_CONCAT () Membuat string gabungan dari argumennya per detail, dan menggabungkan dengan menggabungkannya per grup.

Contoh 1: sederhana

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

Keluaran:

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

Contoh 2: banyak argumen

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

Keluaran:

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

Contoh 3: Menggunakan pemisah khusus

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

Keluaran:

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

Contoh 4: Mengontrol urutan elemen daftar

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

Keluaran:

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

Fitur: COUNT (DISTINCT) dengan banyak ekspresi

Anda dapat menggunakan beberapa ekspresi dalam ekspresi COUNT (DISTINCT ...) untuk menghitung jumlah kombinasi.

SELECT COUNT(DISTINCT CountryCode, Language) FROM CountryLanguage

Fitur / Gotcha: Tidak perlu menyertakan ekspresi non-agregat dalam daftar GROUP BY

Kebanyakan RDBMS-es memberlakukan GROUP BY yang sesuai dengan SQL92 yang mengharuskan semua ekspresi non-agregat dalam daftar SELECT untuk muncul di GROUP BY. Dalam RDBMS-es ini, pernyataan ini:

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

tidak valid, karena daftar PILIH berisi kolom negara.Continent non-agregat yang tidak muncul dalam daftar GROUP BY. Dalam RDBMS-es ini, Anda harus mengubah daftar GROUP BY untuk membaca

GROUP BY   Country.Code, Country.Continent

atau Anda harus menambahkan beberapa agregat non-sense ke Country.Continent, misalnya

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

Nah, masalahnya, secara logis tidak ada yang menuntut negara itu. Benua harus disepakati. Lihat, Country.Code adalah kunci utama dari tabel Negara. Country.Continent juga merupakan kolom dari tabel Country dan dengan demikian menurut definisi secara fungsional bergantung pada kunci utama Country.Code. Jadi, harus ada tepat satu nilai di Country.Continent untuk setiap Country.Code berbeda. Jika Anda menyadarinya, maka Anda menyadari bahwa tidak masuk akal untuk menggabungkannya (hanya ada satu nilai, benar) atau dikelompokkan berdasarkan itu (karena itu tidak akan membuat hasilnya lebih unik karena Anda sudah mengelompokkan sebelumnya. pk)

Anyway - MySQL memungkinkan Anda menyertakan kolom non-agregat dalam daftar SELECT tanpa mengharuskan Anda juga menambahkannya ke klausa GROUP BY.

Gotcha dengan ini adalah bahwa MySQL tidak melindungi Anda jika Anda kebetulan menggunakan kolom non-agregat. Jadi, kueri seperti ini:

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

Akan dijalankan tanpa keluhan, tetapi kolom CountryLanguage.Percentage akan berisi non-sense (artinya, dari semua persentase bahasa, salah satu nilai yang tersedia untuk persentase akan dipilih secara acak atau setidaknya di luar kendali Anda.

Lihat: Membongkar Kelompok Menurut Mitos

segera
sumber
Mengizinkan kolom yang tidak dideklarasikan dalam grup oleh adalah salah satu fitur paling favorit saya yang berasal dari Oracle. Ini masalah besar jika Anda terbiasa dengan Oracle - itu hanya memungkinkan Anda menjalankan kueri, hasilnya terlihat benar, tetapi kemudian Anda menyadari bahwa itu tidak melakukan apa yang Anda pikirkan.
mbafford
7

Perintah "pager" di klien

Jika Anda memiliki, katakanlah, 10.000 baris dalam hasil Anda dan ingin melihatnya (Ini mengasumsikan perintah "kurang" dan "tee" tersedia, yang biasanya terjadi di Linux; di Windows YMMV.)

pager less
select lots_of_stuff FROM tbl WHERE clause_which_matches_10k_rows;

Dan Anda akan mendapatkannya di penampil file "kurang" sehingga Anda dapat membuka halaman dengan baik, mencari, dll.

Juga

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

Akan dengan mudah menulis ke file.

MarkR
sumber
sayangnya di bawah jendela, meskipun "kurang" dan "tee" ada, opsi pager itu sendiri tidak didukung. tidak mudah pula
Berry Tsakala
6

Beberapa hal yang mungkin menarik bagi Anda:

<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
SorinV
sumber
3

Berikut adalah beberapa tip saya - Saya membuat blog tentang mereka di blog saya ( Tautan )

  1. Anda tidak perlu menggunakan tanda '@' saat mendeklarasikan variabel.
  2. Anda harus menggunakan pembatas (defaultnya adalah ';') untuk membatasi akhir pernyataan - Tautan
  3. Jika Anda mencoba memindahkan data antara MS-SQL 2005 dan mySQL, ada beberapa rintangan untuk dilewati - Tautan
  4. Melakukan pencocokan case-sensitive di mySQL - link
Nikhil
sumber
3

Jika Anda akan bekerja dengan database InnoDb transaksi besar dan / atau tinggi, pelajari dan pahami "TUNJUKKAN STATUS INNODB" Mysql Performance Blog , itu akan menjadi teman Anda.

Hawk Kroeger
sumber
3

Jika menggunakan cmdline Mysq, Anda dapat berinteraksi dengan baris perintah (di mesin Linux - tidak yakin apakah ada efek yang setara di Windows) dengan menggunakan tanda jeritan / seru. Sebagai contoh:

\! cat file1.sql

akan menampilkan kode untuk file1.sql. Untuk menyimpan pernyataan dan query Anda ke sebuah file, gunakan fasilitas tee

\T filename

untuk mematikan ini gunakan \ t

Terakhir untuk menjalankan skrip yang sudah Anda simpan, gunakan "nama file sumber". Tentu saja, alternatif normal adalah mengarahkan nama skrip saat memulai mysql dari baris perintah:

    mysql -u root -p < case1.sql

Harapan itu berguna bagi seseorang!

Sunting: Baru ingat satu sama lain - ketika memanggil mysql dari baris perintah Anda dapat menggunakan -t switch sehingga output dalam format tabel - keuntungan nyata dengan beberapa kueri (meskipun tentu saja mengakhiri kueri dengan \ G seperti yang disebutkan di tempat lain di sini juga membantu dalam hal ini). Lebih banyak lagi tentang berbagai switch Command Line Tool

Baru saja menemukan cara yang rapi untuk mengubah urutan sortir (biasanya menggunakan Case ...) Jika Anda ingin mengubah urutan sortir (mungkin urutkan berdasarkan 1, 4, 3, 2, bukan 1, 2, 3, 4) Anda dapat menggunakan fungsi bidang dalam Urutan menurut klausa. Sebagai contoh

Urutkan Berdasarkan Bidang (sortir_field, 1,4,3,2)

DBMarcos99
sumber
3

Saya tidak berpikir ini khusus untuk MySQL, tetapi mencerahkan bagi saya:

Alih-alih menulis

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

Anda tinggal menulis

WHERE (x.id, x.f2) > (y.id, y.f2)
Johan
sumber
Itu benar-benar keren tapi apa beberapa use case untuk ini?
mangoDrunk
Ini bisa berguna untuk menemukan semua catatan yang lebih besar dari catatan yang diberikan.
Fantius
2

mysqlsla - Salah satu alat analisis log kueri lambat yang sangat umum digunakan. Anda dapat melihat 10 kueri terburuk sejak terakhir kali Anda meluncurkan log kueri yang lambat. Ini juga dapat memberi tahu Anda berapa kali kueri BAD dijalankan dan berapa total waktu yang dibutuhkan di server.

pawan
sumber
2

Sebenarnya didokumentasikan , tetapi sangat mengganggu: konversi otomatis untuk tanggal yang salah dan masukan yang salah lainnya.

Sebelum MySQL 5.0.2, MySQL memaafkan nilai data yang ilegal atau tidak tepat dan memaksanya ke nilai legal untuk entri data. Di MySQL 5.0.2 dan yang lebih baru, itu tetap menjadi perilaku default, tetapi Anda dapat mengubah mode SQL server untuk memilih perlakuan yang lebih tradisional untuk nilai-nilai buruk sehingga server menolaknya dan membatalkan pernyataan di mana mereka terjadi.

Adapun tanggal: terkadang Anda akan "beruntung" ketika MySQL tidak menyesuaikan input ke tanggal valid terdekat, tetapi menyimpannya karena 0000-00-00menurut definisi tidak valid. Namun, Anda mungkin ingin MySQL gagal daripada diam-diam menyimpan nilai ini untuk Anda.

Arjan
sumber
1

InnoDB secara default menyimpan semua tabel dalam satu tablespace global yang tidak akan pernah menyusut .

Anda dapat menggunakan innodb_file_per_tableyang akan meletakkan setiap tabel di tablespace terpisah yang akan dihapus ketika Anda menjatuhkan tabel atau database.

Rencanakan sebelumnya karena Anda harus membuang dan memulihkan database untuk mendapatkan kembali ruang jika tidak.

Menggunakan Ruang Tabel Per Tabel

serbaut
sumber
1

Jika Anda memasukkan nilai string kosong ke kolom tanggal waktu "", MySQL akan mempertahankan nilai sebagai 00/00/0000 00:00:00. Tidak seperti Oracle, yang akan menyimpan nilai null.

Devid G
sumber
1

Selama benchmark saya dengan set data besar dan bidang DATETIME, selalu lebih lambat untuk melakukan kueri ini:

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

Dari pendekatan ini:

SELECT * FROM mytable
WHERE date_column BETWEEN '2011-01-01 00:00:00' AND '2011-03-03 23:59:59'
Osvaldo Mercado
sumber