Ne (PHP) ile MySQL için kullanılacak en iyi harmanlama

9 Cevap php

Girdiğiniz ne olacağını% 100 değil genel bir web sitesi için MySQL harmanlama için bir "en iyi" seçim olup olmadığını merak ediyorum? Ben tüm kodlamalar MySQL, Apache, PHP içinde HTML ve bir şey gibi, aynı olması gerektiğini anlıyoruz.

Geçmişte "UTF-8" in çıkış PHP ayarlanır, ancak hangi harmanlama MySQL bu maç yapar? Var Ben UTF-8 olanlardan biri düşünüyorum, ama ben daha önce utf8_unicode_ci, utf8_general_ci ve utf8_bin kullandık.

9 Cevap

(Dil karakterleri karşılaştırırken) ve performans temel fark doğruluğu sıralama olduğunu. Sadece özel bir ikili formatta karakterleri karşılaştırma hangi utf8_bin edilir.

utf8_general_ci biraz daha hızlı utf8_unicode_ci daha, ama (sıralama için) daha az hassas. (Örneğin utf8_swedish_ci gibi) belirli bir dil utf8 kodlama bu dil için sıralamak için onları en doğru kılan ek dil kurallarını içerir. Ben belirli bir dil tercih için iyi bir nedeniniz yoksa ben, (ben küçük bir performans iyileştirmeleri doğruluk tercih) utf8_unicode_ci kullanmak çoğu zaman.

Sen MySQL kılavuzda özel unicode karakter setleri hakkında daha fazla okuyabilirsiniz - http://dev.mysql.com/doc/refman/5.0/en/charset-unicode-sets.html

Utf8_general_ci kullanırken oluşabilir bu sorunun çok, çok farkında olun.

Utf8_general_ci harmanlama kullanılırsa MySQL seçin tablolarında bazı karakterler arasında ayrım yapmaz. Özellikle, örneğin, kullanıcı adları dahil - bu çok pis böcek yol açabilir. Veritabanı tabloları kullanan uygulanmasına bağlı olarak, bu sorun kötü niyetli kullanıcılar, bir yönetici hesabı eşleşen bir kullanıcı adı oluşturmak için izin verebilir.

Bu sorun erken 5.x sürümlerinde en azından kendini ortaya çıkarır - Emin değilim bu davranış sonradan değişti.

Ben hiçbir DBA değilim, ama bu sorunu önlemek için, ben her zaman yerine bir harf duyarsız birinin 'utf8-bin' ile gitmek.

Aşağıdaki komut örnek sorunu açıklar.

-- first, create a sandbox to play in
CREATE DATABASE `sandbox`;
use `sandbox`;

-- next, make sure that your client connection is of the same 
-- character/collate type as the one we're going to test next:
charset utf8 collate utf8_general_ci

-- now, create the table and fill it with values
CREATE TABLE `test` (`key` VARCHAR(16), `value` VARCHAR(16) )
    CHARACTER SET utf8 COLLATE utf8_general_ci;

INSERT INTO `test` VALUES ('Key ONE', 'value'), ('Key TWO', 'valúe');

-- (verify)
SELECT * FROM `test`;

-- now, expose the problem/bug:
SELECT * FROM test WHERE `value` = 'value';

--
-- Note that we get BOTH keys here! MySQLs UTF8 collates that are 
-- case insensitive (ending with _ci) do not distinguish between 
-- both values!
--
-- collate 'utf8_bin' doesn't have this problem, as I'll show next:
--

-- first, reset the client connection charset/collate type
charset utf8 collate utf8_bin

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET utf8 COLLATE utf8_bin;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Note that we get just one key now, as you'd expect.
--
-- This problem appears to be specific to utf8. Next, I'll try to 
-- do the same with the 'latin1' charset:
--

-- first, reset the client connection charset/collate type
charset latin1 collate latin1_general_ci

-- next, convert the values that we've previously inserted
-- in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET latin1 COLLATE latin1_general_ci;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Again, only one key is returned (expected). This shows 
-- that the problem with utf8/utf8_generic_ci isn't present 
-- in latin1/latin1_general_ci
--
-- To complete the example, I'll check with the binary collate
-- of latin1 as well:

-- first, reset the client connection charset/collate type
charset latin1 collate latin1_bin

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET latin1 COLLATE latin1_bin;

-- now, re-check for the bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Again, only one key is returned (expected).
--
-- Finally, I'll re-introduce the problem in the exact same 
-- way (for any sceptics out there):

-- first, reset the client connection charset/collate type
charset utf8 collate utf8_generic_ci

-- next, convert the values that we've previously inserted in the table
ALTER TABLE `test` CONVERT TO CHARACTER SET utf8 COLLATE utf8_general_ci;

-- now, re-check for the problem/bug
SELECT * FROM test WHERE `value` = 'value';

--
-- Two keys.
--

DROP DATABASE sandbox;

Aslında, muhtemelen utf8_unicode_ci veya utf8_general_ci kullanmak istiyorum.

  • tüm aksan uzak sıyırma ve ASCII sanki sıralayarak utf8_general_ci sıralar
  • utf8_unicode_ci Unicode sıralama düzenini kullanır, bu yüzden fazla dilde düzgün sıralar

Eğer sadece İngilizce metin depolamak için bu kullanıyorsanız Ancak, bu farklı olmamalıdır.

Alfabe verileri nasıl sıralanmış ve dizeleri birbirleriyle kıyaslandığında nasıl etkiler. Bu sizin kullanıcıların çoğu bekliyoruz harmanlamayı kullanmak gerektiği anlamına gelir.

Örnek documentation:

utf8_general_ci also is satisfactory for both German and French, except that ‘ß’ is equal to ‘s’, and not to ‘ss’. If this is acceptable for your application, then you should use utf8_general_ci because it is faster. Otherwise, use utf8_unicode_ci because it is more accurate.

Böylece - beklenen kullanıcı bazında ve correct ayırma ihtiyacı ne kadar bağlıdır. İngilizce bir kullanıcı tabanı için, utf8_general_ci İsveççe gibi, özel alfabe oluşturulmuş, diğer diller için yeterli olacaktır.

Esasen, bu bir dize düşünmek nasıl bağlıdır.

Ben her zaman, çünkü Guus tarafından vurgulanan sorun utf8_bin kullanın. Benim düşünceme göre, kadar veritabanı ilgili olması gerektiği gibi, bir dize hala sadece bir dizedir. Bir dize UTF-8 karakter bir sayıdır. Bir karakter bu yüzden neden kullandığınız dil bilmek gerekiyor mu bir ikili gösterimini var? Genellikle, insanlar çok dilli siteler için kapsamı ile sistemler için veritabanları inşa edilecektir. Bu bir karakter kümesi olarak UTF-8 kullanarak tüm noktasıdır. Ben bir pureist biraz ama ben hata riskleri ağır size indekslemesi alabilirsiniz hafif bir avantaja ağır basar düşünüyorum. Herhangi bir dil ile ilgili kurallar DBMS çok daha yüksek bir düzeyde yapılmalıdır.

Benim kitaplarım "değer" bir milyon yıl içinde "değer" eşit olmamalıdır.

Ben bir metin alanı depolamak ve bir harf duyarsız arama yapmak istiyorsanız, böyle düşük (gibi PHP fonksiyonları) ve php fonksiyon strtolower () ile MySQL dize fonksiyonları kullanacağız.

UTF-8 metinsel bilgi için utf8_general_ci kullanmak gerekir, çünkü ...

  • utf8_bin: compare strings by the binary value of each character in the string

  • utf8_general_ci: compare strings using general language rules and using case-insensitive comparisons

aka bunu arama yapma ve daha hızlı veri indeksleme gerektiğini olacak / daha kullanışlı / daha etkili.

Guus tarafından vurgulanmış durumda, ben şiddetle yerine utf8_bin (sıkı eşleştirme, yanlış sipariş) ve utf8_unicode_cs (küçük harf duyarlı, sıkı uyan, çoğunlukla doğru sipariş) kullanarak öneririm.

Alan bir kullanıcı için eşleşen karşı, aranacak amaçlanmıştır ise, utf8_general_ci veya utf8_unicode_ci kullanın. Hem harf duyarsız, biri losely maç olacak ('ß' 's' eşittir değil, 'ss' için). Kaybetmek eşleşen belirtilen dil için daha uygundur utf8_german_ci gibi dil özel versiyonları da vardır.

Kabul cevabı oldukça kesin utf8_unicode_ci kullanımını öneriyor ve yeni projeler için bu harika ederken, ben bunun biraz zaman kimseyi kazandırır sadece durumda benim son aykırı deneyim ilişkilendirmek istedi.

Utf8_general_ci MySQL Unicode için varsayılan harmanlama olduğundan utf8_unicode_ci kullanmak istiyorsanız, o zaman yerlerde bir lot bunu belirtmek zorunda sona.

Örneğin, tüm istemci bağlantıları varsayılan bir karakter kümesi (benim için mantıklı) ama aynı zamanda bir varsayılan harmanlama (harmanlama her zaman unicode için utf8_general_ci varsayılan olacaktır yani) sadece var.

Olasılıkla, veritabanına bağlanmak sizin alanlara, sizin komut için utf8_unicode_ci kullanıyorsanız açıkça istenen harmanlama söz güncelleştirilmesi gerekir - bağlantı varsayılan harmanlama kullanırken, aksi takdirde metin dizelerini kullanarak sorguları başarısız olabilir.

Sonuçta Unicode/UTF8 için herhangi bir boyutta varolan sistemi dönüştürürken, çünkü MySQL varsayılan kolları şekilde utf8_general_ci kullanmak zorunda olan sona olmasıdır.

Casee alan, kullanıcı için eşleşen aksine, aranacak amaçlanmıştır için, daha sonra utf8_general_ce alan bir kullanıcı için eşleşen karşı utf8_general_ci veya utf8_unicode_ci kullanmak ve ardından, aranacak amaçlanmıştır kullanın. Hem harf duyarsız, biri losely maç olacak ('ß' 's' eşittir değil, 'ss' için). Kaybetmek eşleşen dil specified.i veya utf8_unicode_ci için daha uygundur utf8_german_ci gibi dil özel versiyonları da vardır. Hem harf duyarsız, biri losely maç olacak ('ß' 's' eşittir değil, 'ss' için). Kaybetmek eşleşen belirtilen dil için daha uygundur utf8_german_ci gibi dil özel versiyonları da vardır. Guus tarafından vurgulanmış, ben güçlü bir kullanıcı için uyumlu aksine utf8_general_ci veya utf8_unicode_ci kullanın ardından, aranacak amaçlanmıştır ce alanını sipariş, utf8_unicode_cs (küçük harf duyarlı, sıkı uyan birini kullanarak öneririm. Hem harf duyarsız, biri losely olacak maç ('ß' 's' eşittir, ve 'ss' değil). kaybetmek eşleşen çoğunlukla specified.orrectly dil için daha uygundur utf8_german_ci gibi dil özel sürümler,) yerine utf8_bin da vardır (sıkı eşleştirme, yanlış sipariş).

Alan bir kullanıcı için eşleşen karşı, aranacak amaçlanmıştır ise, utf8_general_ci veya utf8_unicode_ci kullanın. Hem harf duyarsız, biri losely maç olacak ('ß' 's' eşittir değil, 'ss' için). Kaybetmek eşleşen belirtilen dil için daha uygundur utf8_german_ci gibi dil özel versiyonları da vardır.