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.

Posted in  | 6 comments

Comments

  1. Avatar Riklaunim said 4 days later:

    Trzecia opcja to Firebird/Interbase. Wymaga conieco nauki ale warto bo jest to baza z wysokiej półki.

  2. Avatar hosiawak said 6 days later:

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

  3. Avatar madyogi said 9 months later:

    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.

  4. Avatar Jarosław Zabiełło said 9 months later:

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

  5. Avatar Marcin Barczyk said about 1 year later:

    A nie mozna bylo tego wszystkiego wsadzic do unikodu, i ewentualnie przy pobieraniu danych ustawic mu client_encoding ???? (Mowa o postgresie)

  6. Avatar dmilith said about 1 year later:

    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

(leave url/email »)

   Comment Markup Help Preview comment