MySQL5 - rehabilitacja
Posted by Jarosław Zabiełło Tue, 30 May 2006 12:04:00 GMT
Po paru godzinach testów i walki z bazami MySQL 5.0.21 i PostgreSQL 8.1.4, muszę zwrócić trochę honoru bazie MySQL. PostgreSQL to bardzo zaawansowana i potężna baza danych, jednakże, jak pisałem wcześniej, ma jeden, zasadniczy feler, który ją wyklucza z moich zastosowań – kiepską obsługę różnych kodowań w ramach jednej bazy danych. Próba napisania aplikacji wielojęzycznej sortującej i wyszukującej z uwzględnianiem wielu różnych języków jest bardzo trudna. Praktycznie nie ma sensu aby do tego użyć PostgreSQL.
Tutaj pokazuje swoje możliwości MySQL 5. na razie nie mam potwierdzonych informacji o słabej stabilności tak jak to było z wersjami wcześniejszymi. Zaś problem dziwacznego zachowania się warunku LIKE… otóż udało mi się za pomocą prób i błędów połączonych z przeszukiwaniem dokumentacji, ustalić ostateczne rozwiązanie.
Po kolei. Wpierw trzeba wiedzieć, że MySQL 5 (choć jest to już od wersji 4.1) udostępnił obsługę wielojęzyczności na znacznie lepszym poziomie niż inne bazy. Otóż można łatwo zdefiniować niezależne traktowanie tekstu dla każdej tabeli w ramach tej samej bazy. Mało tego, można pójść dalej i zdefiniować niezależne kodowanie dla każdego pola tekstowego oddzielnie.
Daje to niebywałą elastyczność i komfort w obsłudze tekstów międzynarodowych. Można bowiem wymusić aby w tekstach polskich działało sortowanie zgodne z zasadami języka polskiego oraz aby duże i małe polskie ogonki były traktowane tak samo przy wyszukiwaniu. Inne pole może posiadać identyczne reguły dla języka niemieckiego, szwedzkiego, itp. itd. Jedynym założeniem jest aby kodowanie takich tabel i/lub pól było w UTF8. To jest wewnętrzny format w jakim trzeba trzymać dane tekstowe. Nie ma on nic wspólnego z kodowaniem jakie uzyskuje klient. Odpada w ogóle konieczność pisania własnych procedur aby to przekodowywać. Cała robotę za nas “odwali” MySQL. Chcesz w swoich skryptach wypluwać do przeglądarki polskie ogonki w formacie ISO-8859-2? Żaden problem. Wywołaj kwerendę “SET NAMES latin2” i potem wykonuj SELECT…
Samo kodowanie znaków to dopiero początek. Chcemy także aby działało sortowanie i wyszukiwanie bez wrażliwości na wielkość liter. Aby to działało należy zadbać o to aby każde pole posiadało odpowiednią definicję tzw. collation. Dla języka polskiego będzie to utf8_polish_ci. Przykładowa definicja tabeli (z dodatkowymi bajerami jakie daje MySQL, np. kompresję indeksów) mogłaby wyglądać np. tak:CREATE TABLE `artykul` (
`id` int(11) NOT NULL auto_increment,
`tytul` varchar(255) collate utf8_polish_ci NOT NULL,
`tresc` text collate utf8_polish_ci NOT NULL,
PRIMARY KEY (`id`),
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_polish_ci PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=COMPRESSED;MySQL udostepnia także słowo COLLATE do bardzo wygodnej obsługi tekstów międzynarodowych. Lista dostępnych języków jest podana w dokumentacji i jest imponująca.
Gdzie leżał zatem problem z dziwnym zachowaniem się bazy? Po prostu nie było zdefinowanego żadnego collation i baza trochę zwariowała. Na pewno byłoby lepiej, aby w takiej sytuacji zachowywała się bardziej przewidywalnie. Ale wystarczyło dodanie definicji odpowiedniego zestawu języka i wszystko wróciło do normy.


Kanały IRC![[Dilber w Onecie]](/images/larry.png)


Trzecia opcja to Firebird/Interbase. Wymaga conieco nauki ale warto bo jest to baza z wysokiej półki.
Możliwość zdefiniowania COLLATE dla danej kolumny w tabeli to duzy plus Mysql 5. To jednak nie przekreśla Postgres’a z zastosowań.
Możesz np. zainstalować funkcję nls_string
i mieć coś takiego pod ręką:
select * from table order by nls_value(name, ‘pl_PL.UTF-8’)
W moim przypadku samo “set names latin2” już załatwiło temat, bez konieczności zamiany kodowania kolumn i tabel na CHARSET=utf8 COLLATE=utf8_polish_ci.
Uwaga bez sensu. SET NAMES latin2 czy cp1250 czy cokolwiek co MySQL obsługuje, ustawia tylko i wyłącznie kodowanie po stronie klienta. Collations zaś to ustawienia lokalizacyjne po stronie serwera. Zapewniają zachowanie się tekstu wg zasad gramatycznych danego języka (nie tylko polskiego!)
A nie mozna bylo tego wszystkiego wsadzic do unikodu, i ewentualnie przy pobieraniu danych ustawic mu client_encoding ???? (Mowa o postgresie)
z moich testów wynika że jedyny “problem” to kwestia Case Sensitivity przy wyszukiwaniu.. PostgreSQL nie potrzebuje kolacji.. bo naturlanie dobrze sobie radzi z sortowaniem zarówno polskich jak i np rosyjskich znaków.. wystarczy bazę mieć na UTF-8