MySQL'deki bir SELECT ifadesi için varsayılan kayıt sırası nedir?


66

Aşağıdaki tablo ve verilere sahip olduğunuzu varsayalım:

create table t (
    k int,
    v int,
    index k(k)
    ) engine=memory;

insert into t (k, v)
values (10, 1),
       (10, 2),
       (10, 3);

Verilirken select * from t where k = 10hiçbir ile order byfıkra, nasıl MySQL varsayılan olarak kayıtları sıralamak geliyor?

Yanıtlar:


75

Yeniden gönderiliyor Cevabımı SQL Server ilgili benzer soruya:

SQL dünyasında, sıra, bir veri kümesinin doğal bir özelliği değildir. Bu nedenle, verilerinizi bir ORDER BY deyimi ile sorgulamadığınız sürece RDBMS’nizden verilerinizin belirli bir sırayla (veya tutarlı bir sırayla) geri döneceğine dair hiçbir garanti alamazsınız.

Yani sorunuzu cevaplamak için:

  • MySQL kayıtları tutar ancak herhangi bir tutarlılık garantisi olmadan ister.
  • Herhangi bir şey için bu siparişe güvenmeyi düşünüyorsanız, kullanarak istediğiniz siparişi belirtmelisiniz ORDER BY. Başka bir şey yapmak, istenmeyen sürprizlere hazırlanmaktır.

Bu sadece MySQL'in değil, tüm SQL'lerin bir malıdır. SQL-92 spec içindeki ilgili metin :

Bir <cümlecikçe sırala> belirtilmemişse, Q satırlarının sırası uygulamaya bağlıdır.

İmleçlerin belirtimlerinde benzer metin parçaları vardır.


26

ORDER BYMadde yokluğundaki satırların sırası şöyle olabilir:

  • herhangi iki depolama motoru arasında farklı;
  • Aynı depolama motorunu kullanıyorsanız, aynı depolama motorunun iki versiyonu arasında farklı olabilir; Buradaki örnek , "Satırların Sıralanması" bölümüne gidin.
  • depolama motoru sürümü aynıysa, ancak MySQL sürümü farklıysa, bu sürümler arasındaki sorgu iyileştirici değişiklikleri nedeniyle farklı olabilir;
  • eğer her şey aynıysa, ay evresi nedeniyle farklı olabilir ve bu sorun değil.

10

Eklemek girişte sıralanmamış, karmakarışık. Yaratılan endeks, indeks olan bağlı listede elemanların uygun yere yerleştirildiği sıraya sahip. Bir dizin öğesi için bir sonrakine hareketli bir bağlantınız, geçiş ve bütünlük amaçları için geriye dönük bir bağlantı ve ardından tablodaki gerçek kayıtlara bir işaretçi kümesi içeren bir dizin için üçlü bir bağlantı listesi düşünün. Söz konusu dizine alınmış öğeyi eşleştirin.

Gerçek veriler, depoda kaotik. Depolama ve yapım sırasında sipariş edilen verilerle ilgili endeks. Sipariş edilen veya sıralanmayan verilerin gerçek olarak çekilmesi, ilgili sorguya bağlıdır.


4

MEMORY depolama motoruna gelince , sıralamanın ekleme sırasına göre olmasını beklerdim çünkü varsayılan dizin düzeni HASHyerine dizini oluşturuyordu BTREEve dizin düzeninin hiçbir yönü kullanılmıyordu. K dizini oluşturduğunuz ve k aynı değer olduğundan, tüm anahtarlar aynı karma kepçeye girer . Bir karma kepçeyi doldurmak için daha fazla karmaşıklık varsaymak için bir neden olmadığından, yerleştirme sırası en anlamlı olanıdır.

Aynı örnek tabloyu ve veriyi INSERTaldım , 30 saniye koştum ve şunu aldım:

mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.00 sec)

mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t values
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+------+
| k    | v    |
+------+------+
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
+------+------+
30 rows in set (0.00 sec)

mysql>

K: 10 ve 11 için iki farklı değer eklemeye karar verdim.

mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.02 sec)

mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.01 sec)

mysql> insert into t values
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+------+
| k    | v    |
+------+------+
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
+------+------+
30 rows in set (0.00 sec)

mysql>

Takma sırasına benziyor. k = 11 ilk anahtarın ardından 10'du. 11 yerine ilk 10'u eklemeye ne dersiniz? Elimde bu var:

mysql> use test
Database changed
mysql> drop table if exists t;
Query OK, 0 rows affected (0.02 sec)

mysql> create table t(k int, v int,index k(k)) engine=memory;
Query OK, 0 rows affected (0.00 sec)

mysql> insert into t values
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (11, 1), (11, 2), (11, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3),
    -> (10, 1), (10, 2), (10, 3), (10, 1), (10, 2), (10, 3);
Query OK, 30 rows affected (0.00 sec)
Records: 30  Duplicates: 0  Warnings: 0

mysql> select * from t;
+------+------+
| k    | v    |
+------+------+
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   11 |    1 |
|   11 |    2 |
|   11 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
|   10 |    1 |
|   10 |    2 |
|   10 |    3 |
+------+------+
30 rows in set (0.00 sec)

mysql>

Oybirliği var !!! YALITIM SİPARİŞİ cevaptır.

MEMORY depolama motoru için dizinleri kullanmaya ilişkin Sidenotes

MEMORY için yapılan aralık aramaları, nispeten korkunç bir performansa sahip olacaktır.

Bir dizin oluştururken, dizinin USING BTREEtanımı ile birlikte yan tümce belirtebilirsiniz . Bu, aralık sorguları için işleri geliştirir.

Belirli bir satır için arama yapmak, ya HASHda ile aynı performansı verir BTREE.

GÜNCELLEME 2011-09-22 11:18 EDT

Bugün ilginç bir şey öğrendim. @Laurynas Biveinis tarafından Percona'dan sağlanan bağlantıyı okudum: Percona bağlantısı MySQL 5.5.15 için MEMORY tabloları hakkında bir şeyler söylüyor :

Satır Siparişi

SİPARİŞ BY yokluğunda, kayıtları önceki MEMORY uygulamasından farklı bir sırayla iade edilebilir. Bu bir hata değil. Bir ORDER BY deyimi olmadan belirli bir siparişe dayanan herhangi bir uygulama beklenmeyen sonuçlar verebilir. ORDER BY olmadan belirli bir düzen, küçük MySQL sürümleri arasında değişebilecek ve değişecek olan bir depolama motorunun ve sorgu iyileştirici uygulamasının bir yan etkisidir.

Bu, bugün görmem için iyi bir bağlantıydı. Verdiğim cevap, yüklediğim tablonun MySQL 5.5.12'de BUGÜN beklemesini beklemek amacıyla alındığını gösterdi. Percona ve @Laurynas Biveinis’in işaret ettiği gibi , başka bir küçük sürümde garanti yoktur.

Bu yüzden cevabımı savunmaya çalışmak yerine, @Laurynas Biveinis'in cevabını yükseltmeyi tercih ederim çünkü en güncel bilgi bu. @Laurynas Biveinis için şeref ve şapkalar . @Eevar'a , sorulara versiyona özel cevaplar vermemeyi kibarca gösterdiği için teşekkür ediyorum . İkisi de bugün benim oyumu alıyor.

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.