Днес си играх да оптимизирам една бавна SQL заявка от вида


SELECT * FROM 'table' WHERE `field` LIKE '%word%'

Къде е проблемният момент тука – последната част ‘%word%’ и в още по-голяма конкретност знака % преди думата, за която правим. Wildcard символът % ,преди която и да е стойност, директно ни превръща заявката директно в бавна, защото по този начин заявката ни спира да ползва индекси на полето. Решения както винаги има, но не винаги са ясни 😆 Общо взето MySQL си имат решение на тоя проблем с fulltext search индексиране на полето. Как става смяната на полето има много написано в документацията, но набързо ще опиша как се променя горната заявка, защото ще стигнем и до една малка драма накрая. Следка като приложим fulltext на полето горе, заявката трябва да се промени във вида:


SELECT * FROM `table` WHERE MATCH (field) AGAINST ('word')

Така структурата е очевидна и няма нужда от излишна дискусия. Горната заявка ще влезе в сила, ако думата, за която правите заявка е поне 4 символа, по подразбиране е това стойността, ако искате да я модифицирате трябва да укажете стойността, която желаете в my.cnf в частта  [mysqld] с декларацията ft_min_word_len=3 или 2, 1 не е добър избор очевидно 😉  . След като смените стойността и рестартирате mysql server-a трябва да направите repair на таблиците си, за да може новото индексиране да влезе в сила. До тук всичко ясно: правя промените, рестартирам, ребилдвам индексите и правя заявката и ми връща 0 реда 😀 Проверявам с


SHOW VARIABLES

Виждам че стойностите, който съм задал са влезли в сила, ребилдвам пак индексите – същия резултат. 🙄 Неприятно, много неприятно. От тук нататък започна едно голямо ругаене и ровене за ключа за бараката 😀 Който се оказа доста, доста интересен. Като цяло, като започнах да чета документацията за не знам кой път и стигнах до един интересен пасаж

 Such a technique works best with large collections (in fact, it was carefully tuned this way). For very small tables, word distribution does not adequately reflect their semantic value, and this model may sometimes produce bizarre results. For example, although the word “MySQL” is present in every row of the articles table shown earlier, a search for the word produces no results

ГРЕДА 😳  Дам табличката ми беше малка – все пак беше тестова. Наших заявката в една голяма таблица с над 2 000 000 реда и там нещата заспаха. Добре вече е ясен проблемът. За да стане ясно решението, ще спомена накратко, че full text search поддържа 3 разширени режима BOOLEAN , EXPRESSIONS и NATURAL LANGUAGE като последния работи по подразбиране. За различните режими може да проверите документацията, аз ще обясня с 2-3 думи за BOOLEAN понеже в него е разковничето. Той поддържа логически оператори от типа AND, OR , NOT и прочие и може да се правят разни магии с търсените фрази, да има една, да няма друга и прочие. Поддържа и символа *, който е еквивалент на wildcard символа % 😉 Той е полезен, когато търсената дума е под дължината на ft_min_word_len или за малки таблички ;). Поне при мен на таблица с около 100 реда върши идеална работа. Остана само да видим и завършената заявка:


SELECT * FROM `table` WHERE MATCH (field)
AGAINST ('*word*' IN BOOLEAN MODE)

Тука вече идва момент дали ни работи индексирането с wildcard символа – отговорът е не знам. Принципно мисля, че да, защото не е казано друго в документацията, но в документацията очевидно не се казват или показват много неща 😀

Enhanced by Zemanta

Мале как ги мразя тия пичове от Mysql 😆 Днес си направих обновлението от mysql 5.1 до 5.5 версия и отново сървъра не запали, a в mysql log-а всичко умираше чисто и просто с:

110527  9:27:38 [ERROR] Unknown/unsupported storage engine: InnoDB
110527  9:27:38 [ERROR] Aborting

Хах се сети какво става 😀 След като почнах да забранявам настройки по my.cfg нещата палнаха чак след като забраних

skip-innodb

Луда работа 🙂 Без тази опция в конфигурацията всичко си работеше както хората, обаче това положение не ме устройваше, защото innodb не се ползва на тоя сървър и няма нужда да заема излишна памет, която така или иначе е оскъдна. След известно ровене открих проблема и съответното му решение. Ако не е зададена default storage engine сървъра няма да опознае командата и съответно няма да се стартира 😯 . Чини ми се че леко вече прекалиха в предишния си ъпгрейд от 5.0 към 5.1 нещата пак бяха с драми поне 10 от параметрите в my.cfg бяха с различни имена и поне 5 бяха драматично изрязани и не поддържани. Тоя път само един проблем 😀 Решението на проблема очевидно е задаване на default storage engine, което става с следната команда

default-storage-engine=MyISAM

От тук нататък всичко си работеше по старо му.

Преди да започна с глупостите искам да кажа, че не съм много напред с web hosting-а и всичко което ще напиша е опит които съм придобил в последните 2-3 месеца. Администрирам едни доста натоварен VPS по посещаемост според tyxo е в топ 80 но влиза в топ 70 ;). Та мисълта ми е, че вече след толкова време придобих разни навици и достигнах до добрите практики по един или друг начин (обикновено по трудния) :D. Няма да пиша или да навлизам в детайли на конфигурацията никак даже. По скоро ще споделя идеите над които да помислите.

  1. Обновявайте софтуера редовно. Apache, php mysql всичко си иска обновления. Дали за да закърпите дупки в сигурниста, дали заради поправени бъгове или нови възможности. Винаги дръжте софтуера си в крак с времето. По принцип рядко се пробива един сървър през апликациите обикновено през дупки в кода на хостваните неща се пробива ама да не разчитаме само на това.
  2. Apache – web server-а ви не е желателно да има активни повече модули от тези които реално ползвате. Колкото повече модули по- бавна работа.
  3. Повече потребители на същия сървър – opcode cache. Преди време писах пък и zerdion направи доволно тестове и се вижда реално ползата от тая магия. В моя случай съм избрал eAccelerator защото в реална работна среда той показва най добри резултати с пуснати всички настройки към него. По бързо зареждане по малко ядене на ресурси което респективно означава повече потребители.
  4. Притискат ви с трафика – gzip. Най лесния начин да намалите реални трафик които правите е с gzip компресия на http отговорите към клиента. Mod deflate е решението за apache. За други http server-и не съм проучвал въпроса :). Реално около 50% ми падна трафика при компресия върху html,css,js,xml. Трябва да проверя дали мога да компресирам и друг вид съдържание ще е интересно. Защото реално снимките са съдържанието което прави най много трафик в един сайт.
  5. mysql serer – горещо ви препоръчвам ако не сте се наградили с версия 5.1 да го направите. Като цяло Oracle имат някакъв малък опит с бази данни 😆 и тоя опит са го вкарали добре в 5.1 версията не съм пробвал 5.5 но и това планувам да стане скоро.  Определено се ускори работата на sql заявките може би леко падна натоварването но с не повече от 5-6% но a пък и новите функционалности за програмистите са прекрасни. Основаната такава partitions. При надграждане внимавайте какви настройки имате в my.cfg Не всички стари опции са валидни, също е добре да махнете старите библиотеки поне при CentOS 5.5 направиха проблеми при Debian нямах такива ядове. След това си вижте mysql log-а защото някои от опциите са с различни имена и е добре да ги промените ако след време минете към 5.5 да не се чудите защо не палва конфигурацията ви.
  6. sql заявките.  Задължително разрешете опцията за записване на slow query. По тези дневници можете да върнете информация на програмистите ако не сте вие за бавните заявки да се оптимизират. Колкото по малко такива заявки по малко натоварване за сървъра ви 😉
  7. Малко защита – сменете подразбиращия се порт на ssh-а ви няма нужда смотани ботове да се опитват да ви хакват. Apache го подсигурете с mod_security доста полезен модул прави филтрация на доста шитни – sql inj, rfi DDoS и прочие. Няма да спре голям хахор ама поне ламерите ще ги отсее. PHP е добра идея да се защити с Suhosin. Може да се сложи като допълнително разширение или направо като пач в php кода. Аз лично предпочитам първия по изчистен ми се струва.

Като за начало това са нещата които се сещам. Не са много а като се замисля съм направил доста оптимизации по сървъра но много от тях са доста специфични според ситуацията и няма смисъл да ги обяснявам тях като например лимитации на кешове или пък колко процеса има вдигнато apache-то. Вероятно с времето ще се сещам и за още неща които са как да кажа част от малките неща които дават големия резултат. Машината е доста добре оптимизирана за сравнение ние правим на 20к уникални посещения на ден и сме на най ниския възможен vps план load time на страниците ние не надхвърля 1,5-2 сек или ако го надхвърля е заради външните източници на реклами иначе самата страница се изплюва за части от секундата. Хора с близки позиции до нас са с не оптимизирани сървъри с доста повече ресурси от нашия и имат същите резултати. Общо взето оптимизиране му е майката и пиенето на бира бащата 😆

ps Песничката леко се връзва с тематиката 😀

Днес phpmyadmin-a ми изтрещя без никаква видима причина с следната груба грешка

Cannot start session without errors, please check errors given in your PHP and/or webserver log file and configure your PHP installation properly.

Общо взето проблема е елементарен променливата session.save path в php.ini фаила беше без стоиност. Мистиката се развърза като се сетих че направих упгреид на на php версията ми и тогава вероятно по невнимание съм замал старите настроики, а днес рестартирах сървъра, че беше почнал да пълни swap-a заради едно зомби 🙂