Уроците от работата ми по WordPress.com - Веселин Николов

51
Уроците от работата ми по WordPress.com Веселин Николов

Transcript of Уроците от работата ми по WordPress.com - Веселин Николов

Page 1: Уроците от работата ми по WordPress.com - Веселин Николов

Уроците от работата ми по WordPress.com

Веселин Николов

Page 2: Уроците от работата ми по WordPress.com - Веселин Николов

За мен

● Веселин Николов● @dzver● Работя в Automattic● PHP, MySQL,

WordPress

Page 3: Уроците от работата ми по WordPress.com - Веселин Николов

Работата ми преди

● MS SQL Server 2005● MySQL < 5.1, 5.1● 1-2-3 сървъра● Сложни схеми● Недостатъчни ресурси

Page 4: Уроците от работата ми по WordPress.com - Веселин Николов

Работата ми преди

● Stored Procedures● Triggers● SQL Jobs живеещи в DB сървъра● Конструирани заявки с много случаи● Materialized Views● Foreign Keys

● Продължителна замяна на логика с курсори с логика без курсори

Page 5: Уроците от работата ми по WordPress.com - Веселин Николов

Умножете по 1000

● Проблеми с натоварване и много работа по оптимизиране на сложните заявки

● Денормализация● Много промени в схемата

Page 6: Уроците от работата ми по WordPress.com - Веселин Николов

После си смених работата.

Page 7: Уроците от работата ми по WordPress.com - Веселин Николов

Шок

● Примитивни заявки, предимно primary key lookups. Join decomposition.

● Редки и твърде скъпи промени в схемата● Нови проблеми като replication lag и риск от

чупене услугата

Page 8: Уроците от работата ми по WordPress.com - Веселин Николов
Page 9: Уроците от работата ми по WordPress.com - Веселин Николов

Работата ми сега

● MySQL● Прости заявки● Огромни обеми заявки● Множество сървъри● WordPress● Memcached

Page 10: Уроците от работата ми по WordPress.com - Веселин Николов

Често срещани проблеми

● Много на брой заявки● Заявки по големи таблици без индекси● Offsets● Много сортиране● Избиране на голям обем данни

Page 11: Уроците от работата ми по WordPress.com - Веселин Николов

Често срещани проблеми

● Много на брой заявки● Заявки по големи таблици без индекси● Offsets● Много сортиране● Избиране на голям обем данни

Page 12: Уроците от работата ми по WordPress.com - Веселин Николов

Много на брой заявки

● Нещо много навътре в кода вика не-кеширана заявка.

Page 13: Уроците от работата ми по WordPress.com - Веселин Николов

Решения

● WordPress Debug Bar

https://wordpress.org/plugins/debug-bar/

● WordPress Options API

http://codex.wordpress.org/Options_API

● Caching

wp_cache_set, wp_cache_get

Page 14: Уроците от работата ми по WordPress.com - Веселин Николов

Debug Bar

● В тестова среда показва всички заявки● Може да показва и всички hooks, remote

requests, memcached stats etc.

Page 15: Уроците от работата ми по WordPress.com - Веселин Николов

Log

● MySQL Slow Log вече поддържа 0 сек● Може да се ползва pt-query-digest● SHOW FULL PROCESSLIST● SHOW PROFILE

● MS SQL има безкрайно удобен профайлър :-)

Page 16: Уроците от работата ми по WordPress.com - Веселин Николов

Options API

● Таблица с keys и values● Кеширана е като 1 масив за blog● Масивът се съхранява в глобална

променлива (чрез object cache)● Инвалидация на кеша при set/add/delete

=> 1 заявка на много хиляди requests

Page 17: Уроците от работата ми по WordPress.com - Веселин Николов

Кеширане

● Не е нужно да се кешира всичко● Има много нива на кеширане

- Object Cache

- Query Cache

- Memcached

- Batcache

И понякога денормализация

Page 18: Уроците от работата ми по WordPress.com - Веселин Николов

Кеширане. MySQL Query Cache

Query Cache = 0

● Кешът се инвалидира при всеки insert/update● Овърхедът често е по-голям от ползите● В някои случаи е полезен, но в рамките на

„десетки мегабайти“.

Page 19: Уроците от работата ми по WordPress.com - Веселин Николов

Кеширане. Batcache

WordPress plugn за съхраняване на цели страници в Memcache или APC

● http://evansolomon.me/notes/faster-wordpress-multisite-nginx-batcache/

● https://wordpress.org/plugins/batcache/

● http://xkcd.com/908/

Page 20: Уроците от работата ми по WordPress.com - Веселин Николов

wp_cache_get, object cache

● wp_cache_get, wp_cache_add, wp_cache_set, wp_cache_delete

● Object Cache за избягване на повторни обръщения към Memcahce

Page 21: Уроците от работата ми по WordPress.com - Веселин Николов

Често срещани проблеми

● Много на брой заявки● Заявки по големи таблици без индекси● Offsets● Много сортиране● Избиране на голям обем данни

Page 22: Уроците от работата ми по WordPress.com - Веселин Николов

Липса на индекс

ALTER `table` ADD index ..

Всеки сложен проблем има едно просто решение, което обикновено е грешно.

Page 23: Уроците от работата ми по WordPress.com - Веселин Николов

Липса на индекс

● Индексите са скъпи● Обновяването им натоварва сървъра● Поддържането им в паметта е скъпо● Допълнителен овърхед за query optimizer

● Не е голяма беля, ако не се събират в паметта.

Page 24: Уроците от работата ми по WordPress.com - Веселин Николов

Често срещани проблеми

● Много на брой заявки● Заявки по големи таблици без индекси● Твърде много индекси● Offsets● Много сортиране● Избиране на голям обем данни

Page 25: Уроците от работата ми по WordPress.com - Веселин Николов

Липса на индекс - решения

● Употреба на прости заявки● Отбягване на комплексни JOINs● EXPLAIN SELECT преди commit● Primary Key само по `id`

данните са клъстърирани по PK, употреба на комплексен PK може да е полезна в някои приложения

Page 26: Уроците от работата ми по WordPress.com - Веселин Николов

Липса на индекс

For join queries, the number of possible plans investigated by the MySQL optimizer grows exponentially with the number of tables referenced in a query.

http://dev.mysql.com/doc/refman/5.7/en/controlling-query-plan-evaluation.html

Page 27: Уроците от работата ми по WordPress.com - Веселин Николов

Малко за индексите

При индекси върху повече от 1 поле, редът има значение:

INDEX foo(A, B, C) � � � � � � � � � � �● WHERE A = 3● WHERE A = 3, B = 4, C = 5

� � � � � � � � � � � � � � �● WHERE B = 5, C = 7

Page 28: Уроците от работата ми по WordPress.com - Веселин Николов

Често срещани проблеми

● Много на брой заявки● Заявки по големи таблици без индекси● Твърде много индекси● Offsets● Много сортиране● Избиране на голям обем данни

Page 29: Уроците от работата ми по WordPress.com - Веселин Николов

Offsets

http://mysite.com/offers/3

SELECT * FROM ...

LIMIT 30, 10

http://mysite.com/offers/309091

SELECT * FROM ...

LIMIT 3090910, 10

Page 30: Уроците от работата ми по WordPress.com - Веселин Николов

Offsets

Такива ситуации възникват при

● Страници● One-time скриптове● Cronjobs, нотификации, какво ли не.

Page 31: Уроците от работата ми по WordPress.com - Веселин Николов

Offsets

Прости решения:

SELECT * FROM ...

WHERE `id` > 1093029 LIMIT 20

SELECT * FROM ...

WHERE `ts` BETWEEN '2014-04-11' AND ...

Page 32: Уроците от работата ми по WordPress.com - Веселин Николов

Offsets

Сложно решение:

SELECT * FROM `table` JOIN (

SELECT `id` FROM `table`

ORDER BY `whatever`LIMIT 5000,50

) as `b` USING `id`

Page 33: Уроците от работата ми по WordPress.com - Веселин Николов

Често срещани проблеми

● Много на брой заявки● Заявки по големи таблици без индекси● Offsets● Много сортиране● Избиране на голям обем данни

Page 34: Уроците от работата ми по WordPress.com - Веселин Николов

Сортиране

Using filesort; Using temporary;

● Не е rocket science● Сортиране по индексирана колона● Индексът е подреден● Ако подходящ индекс за вашата заявка,

сървърът ползва filesort

Page 35: Уроците от работата ми по WordPress.com - Веселин Николов

Сортиране

SELECT * FROM `table`

WHERE A = 3 ORDER BY B

...

ORDER BY A DESC, B DESC

За такава заявка е нужен индекс по A, B (в този ред)

Page 36: Уроците от работата ми по WordPress.com - Веселин Николов

Още малко за индекси...

INDEX(A,B) няма да се ползва при:● WHERE A > 5 ORDER BY B

● WHERE 1=1 ORDER BY B

● ORDER BY A DESC, B ASC

http://www.percona.com/files/presentations/WEBINAR-MySQL-Indexing-Best-Practices.pdf

Page 37: Уроците от работата ми по WordPress.com - Веселин Николов

Antipattern

● ORDER BY RAND()

� � � � � � � � � � � :

WHERE ID IN (5, 14, 33)

WHERE ID > %d LIMIT 1

shuffle();

Page 38: Уроците от работата ми по WordPress.com - Веселин Николов

Antipattern

Употребата на функции в заявките прави безполезен Query Cache

SELECT * FROM `table`

WHERE my_date = current_date()

SELECT * FROM `table`

WHERE my_date = '2014-05-19'

Page 39: Уроците от работата ми по WordPress.com - Веселин Николов

SELECT на много данни

● Cronjobs, one-time scripts● Вътрешно паджиниране по ID● Работа с блокове от по 100-1000 записа

Page 40: Уроците от работата ми по WordPress.com - Веселин Николов

WordPress.com специфики

● 500 000 000+ таблици● 600+ DB сървъра● Master/Slave, partitions, shards, често

таблиците са на различни сървъри● HyperDB to rule them all

Page 41: Уроците от работата ми по WordPress.com - Веселин Николов

HyperDB

● HyperDB е мощен DB клас● Поддаржа репликация● Парсва заявките, за да открие към кои

сървъри да се закачи● Поддържа read и write servers● Поддържа partitions

Page 42: Уроците от работата ми по WordPress.com - Веселин Николов

HyperDB

● Обичайно чете от slaves (read servers)● Винаги пише в masters● При UPDATE/INSERT преминава към master

сървър за дадената таблица

Page 43: Уроците от работата ми по WordPress.com - Веселин Николов

Replication Lag

● Мастър сървърът получава заявка

● Заявката се записва в бинлог

● Заявката се изпълнява на мастъра

● Слейвът създава thread, който се закача към мастъра и изисква новите заявки

● Мастърът създава binlog dump за всеки слейв

● Слейв сървърът изпълнява заявките

http://barry.wordpress.com/2011/07/20/hyperdb-lag-detection/

Page 44: Уроците от работата ми по WordPress.com - Веселин Николов

Replication Lag

Много неща могат да се счупят:● Слейвът може да не може да изпълни заявките със

същата скорост

● Бавни заявки на слейва или explicit locks могат да принудят нишката, която синхронизира да чака

● Бавните заявки на мастъра ще са все така бавни и на слейва

● Disk I/O, Network issues

Page 45: Уроците от работата ми по WordPress.com - Веселин Николов

Replication Lag

Защо е лошо:● Възможно е да се прочетат стари данни● Възможно е да се запишат стари данни

● HyperDB знае кои сървъри са лагнати, но това не ни спасява да мислим заявките си.

Page 46: Уроците от работата ми по WordPress.com - Веселин Николов

WordPress.com специфики

● Предпочитаме голямо количество малки заявки пред малко количество големи

● Таблиците може да не се виждат една друга в текущия connection на HyperDB

● Рядко ползваме JOINS

Page 47: Уроците от работата ми по WordPress.com - Веселин Николов

WordPress.com специфики

● Употребата на дебели JOINS във вашия проект може да е оправдана

● Избягвайте correlated subqueries● Ако базата данни поддържа

материализирани изгледи, why not? (CouchDB, MS SQL, PostgreSQL)

Page 48: Уроците от работата ми по WordPress.com - Веселин Николов

Joins...

● Полетата, които се ползват в ON / USING трябва да са с индекси

● GROUP BY / ORDER BY трябва да са по една таблица

● Ползвайте JOIN вместо всякакви форми на subquery

Page 49: Уроците от работата ми по WordPress.com - Веселин Николов

Търсене

● LIKE '%foo%' - лоша идея.● LIKE 'foo%' - възможен индекс● MATCH ( name ) AGAINST ( 'foo' ) - Full Text

Search (поддържа се от MyISAM и InnoDB MySQL 5.6+)

● SphinxSearch, Lucene, Solr, ElasticSearch

Page 50: Уроците от работата ми по WordPress.com - Веселин Николов

AMA

Page 51: Уроците от работата ми по WordPress.com - Веселин Николов

Благодаря!