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

366 views

Published on

0 Comments
1 Like
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
366
On SlideShare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
3
Comments
0
Likes
1
Embeds 0
No embeds

No notes for slide

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

  1. 1. Уроците от работата ми по WordPress.com Веселин Николов
  2. 2. За мен ● Веселин Николов ● @dzver ● Работя в Automattic ● PHP, MySQL, WordPress
  3. 3. Работата ми преди ● MS SQL Server 2005 ● MySQL < 5.1, 5.1 ● 1-2-3 сървъра ● Сложни схеми ● Недостатъчни ресурси
  4. 4. Работата ми преди ● Stored Procedures ● Triggers ● SQL Jobs живеещи в DB сървъра ● Конструирани заявки с много случаи ● Materialized Views ● Foreign Keys ● Продължителна замяна на логика с курсори с логика без курсори
  5. 5. Умножете по 1000 ● Проблеми с натоварване и много работа по оптимизиране на сложните заявки ● Денормализация ● Много промени в схемата
  6. 6. После си смених работата.
  7. 7. Шок ● Примитивни заявки, предимно primary key lookups. Join decomposition. ● Редки и твърде скъпи промени в схемата ● Нови проблеми като replication lag и риск от чупене услугата
  8. 8. Работата ми сега ● MySQL ● Прости заявки ● Огромни обеми заявки ● Множество сървъри ● WordPress ● Memcached
  9. 9. Често срещани проблеми ● Много на брой заявки ● Заявки по големи таблици без индекси ● Offsets ● Много сортиране ● Избиране на голям обем данни
  10. 10. Често срещани проблеми ● Много на брой заявки ● Заявки по големи таблици без индекси ● Offsets ● Много сортиране ● Избиране на голям обем данни
  11. 11. Много на брой заявки ● Нещо много навътре в кода вика не- кеширана заявка.
  12. 12. Решения ● 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
  13. 13. Debug Bar ● В тестова среда показва всички заявки ● Може да показва и всички hooks, remote requests, memcached stats etc.
  14. 14. Log ● MySQL Slow Log вече поддържа 0 сек ● Може да се ползва pt-query-digest ● SHOW FULL PROCESSLIST ● SHOW PROFILE ● MS SQL има безкрайно удобен профайлър :-)
  15. 15. Options API ● Таблица с keys и values ● Кеширана е като 1 масив за blog ● Масивът се съхранява в глобална променлива (чрез object cache) ● Инвалидация на кеша при set/add/delete => 1 заявка на много хиляди requests
  16. 16. Кеширане ● Не е нужно да се кешира всичко ● Има много нива на кеширане - Object Cache - Query Cache - Memcached - Batcache И понякога денормализация
  17. 17. Кеширане. MySQL Query Cache Query Cache = 0 ● Кешът се инвалидира при всеки insert/update ● Овърхедът често е по-голям от ползите ● В някои случаи е полезен, но в рамките на „десетки мегабайти“.
  18. 18. Кеширане. Batcache WordPress plugn за съхраняване на цели страници в Memcache или APC ● http://evansolomon.me/notes/faster-wordpress-multisite-nginx-batcache/ ● https://wordpress.org/plugins/batcache/ ● http://xkcd.com/908/
  19. 19. wp_cache_get, object cache ● wp_cache_get, wp_cache_add, wp_cache_set, wp_cache_delete ● Object Cache за избягване на повторни обръщения към Memcahce
  20. 20. Често срещани проблеми ● Много на брой заявки ● Заявки по големи таблици без индекси ● Offsets ● Много сортиране ● Избиране на голям обем данни
  21. 21. Липса на индекс ALTER `table` ADD index .. Всеки сложен проблем има едно просто решение, което обикновено е грешно.
  22. 22. Липса на индекс ● Индексите са скъпи ● Обновяването им натоварва сървъра ● Поддържането им в паметта е скъпо ● Допълнителен овърхед за query optimizer ● Не е голяма беля, ако не се събират в паметта.
  23. 23. Често срещани проблеми ● Много на брой заявки ● Заявки по големи таблици без индекси ● Твърде много индекси ● Offsets ● Много сортиране ● Избиране на голям обем данни
  24. 24. Липса на индекс - решения ● Употреба на прости заявки ● Отбягване на комплексни JOINs ● EXPLAIN SELECT преди commit ● Primary Key само по `id` данните са клъстърирани по PK, употреба на комплексен PK може да е полезна в някои приложения
  25. 25. Липса на индекс 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
  26. 26. Малко за индексите При индекси върху повече от 1 поле, редът има значение: INDEX foo(A, B, C) ● WHERE A = 3 ● WHERE A = 3, B = 4, C = 5 ● WHERE B = 5, C = 7
  27. 27. Често срещани проблеми ● Много на брой заявки ● Заявки по големи таблици без индекси ● Твърде много индекси ● Offsets ● Много сортиране ● Избиране на голям обем данни
  28. 28. Offsets http://mysite.com/offers/3 SELECT * FROM ... LIMIT 30, 10 http://mysite.com/offers/309091 SELECT * FROM ... LIMIT 3090910, 10
  29. 29. Offsets Такива ситуации възникват при ● Страници ● One-time скриптове ● Cronjobs, нотификации, какво ли не.
  30. 30. Offsets Прости решения: SELECT * FROM ... WHERE `id` > 1093029 LIMIT 20 SELECT * FROM ... WHERE `ts` BETWEEN '2014-04-11' AND ...
  31. 31. Offsets Сложно решение: SELECT * FROM `table` JOIN ( SELECT `id` FROM `table` ORDER BY `whatever` LIMIT 5000,50 ) as `b` USING `id`
  32. 32. Често срещани проблеми ● Много на брой заявки ● Заявки по големи таблици без индекси ● Offsets ● Много сортиране ● Избиране на голям обем данни
  33. 33. Сортиране Using filesort; Using temporary; ● Не е rocket science ● Сортиране по индексирана колона ● Индексът е подреден ● Ако подходящ индекс за вашата заявка, сървърът ползва filesort
  34. 34. Сортиране SELECT * FROM `table` WHERE A = 3 ORDER BY B ... ORDER BY A DESC, B DESC За такава заявка е нужен индекс по A, B (в този ред)
  35. 35. Още малко за индекси... 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
  36. 36. Antipattern ● ORDER BY RAND() : WHERE ID IN (5, 14, 33) WHERE ID > %d LIMIT 1 shuffle();
  37. 37. Antipattern Употребата на функции в заявките прави безполезен Query Cache SELECT * FROM `table` WHERE my_date = current_date() SELECT * FROM `table` WHERE my_date = '2014-05-19'
  38. 38. SELECT на много данни ● Cronjobs, one-time scripts ● Вътрешно паджиниране по ID ● Работа с блокове от по 100-1000 записа
  39. 39. WordPress.com специфики ● 500 000 000+ таблици ● 600+ DB сървъра ● Master/Slave, partitions, shards, често таблиците са на различни сървъри ● HyperDB to rule them all
  40. 40. HyperDB ● HyperDB е мощен DB клас ● Поддаржа репликация ● Парсва заявките, за да открие към кои сървъри да се закачи ● Поддържа read и write servers ● Поддържа partitions
  41. 41. HyperDB ● Обичайно чете от slaves (read servers) ● Винаги пише в masters ● При UPDATE/INSERT преминава към master сървър за дадената таблица
  42. 42. Replication Lag ● Мастър сървърът получава заявка ● Заявката се записва в бинлог ● Заявката се изпълнява на мастъра ● Слейвът създава thread, който се закача към мастъра и изисква новите заявки ● Мастърът създава binlog dump за всеки слейв ● Слейв сървърът изпълнява заявките http://barry.wordpress.com/2011/07/20/hyperdb-lag-detection/
  43. 43. Replication Lag Много неща могат да се счупят: ● Слейвът може да не може да изпълни заявките със същата скорост ● Бавни заявки на слейва или explicit locks могат да принудят нишката, която синхронизира да чака ● Бавните заявки на мастъра ще са все така бавни и на слейва ● Disk I/O, Network issues
  44. 44. Replication Lag Защо е лошо: ● Възможно е да се прочетат стари данни ● Възможно е да се запишат стари данни ● HyperDB знае кои сървъри са лагнати, но това не ни спасява да мислим заявките си.
  45. 45. WordPress.com специфики ● Предпочитаме голямо количество малки заявки пред малко количество големи ● Таблиците може да не се виждат една друга в текущия connection на HyperDB ● Рядко ползваме JOINS
  46. 46. WordPress.com специфики ● Употребата на дебели JOINS във вашия проект може да е оправдана ● Избягвайте correlated subqueries ● Ако базата данни поддържа материализирани изгледи, why not? (CouchDB, MS SQL, PostgreSQL)
  47. 47. Joins... ● Полетата, които се ползват в ON / USING трябва да са с индекси ● GROUP BY / ORDER BY трябва да са по една таблица ● Ползвайте JOIN вместо всякакви форми на subquery
  48. 48. Търсене ● LIKE '%foo%' - лоша идея. ● LIKE 'foo%' - възможен индекс ● MATCH ( name ) AGAINST ( 'foo' ) - Full Text Search (поддържа се от MyISAM и InnoDB MySQL 5.6+) ● SphinxSearch, Lucene, Solr, ElasticSearch
  49. 49. AMA
  50. 50. Благодаря!

×