- Поисковые системы
- Практика оптимизации
- Трафик для сайтов
- Монетизация сайтов
- Сайтостроение
- Социальный Маркетинг
- Общение профессионалов
- Биржа и продажа
- Финансовые объявления
- Работа на постоянной основе
- Сайты - покупка, продажа
- Соцсети: страницы, группы, приложения
- Сайты без доменов
- Трафик, тизерная и баннерная реклама
- Продажа, оценка, регистрация доменов
- Ссылки - обмен, покупка, продажа
- Программы и скрипты
- Размещение статей
- Инфопродукты
- Прочие цифровые товары
- Работа и услуги для вебмастера
- Оптимизация, продвижение и аудит
- Ведение рекламных кампаний
- Услуги в области SMM
- Программирование
- Администрирование серверов и сайтов
- Прокси, ВПН, анонимайзеры, IP
- Платное обучение, вебинары
- Регистрация в каталогах
- Копирайтинг, переводы
- Дизайн
- Usability: консультации и аудит
- Изготовление сайтов
- Наполнение сайтов
- Прочие услуги
- Не про работу
VK приобрела 70% в структуре компании-разработчика red_mad_robot
Которая участвовала в создании RuStore
Оксана Мамчуева
Маркетинг для шоколадной фабрики. На 34% выше средний чек
Через устранение узких мест
Оксана Мамчуева
Авторизуйтесь или зарегистрируйтесь, чтобы оставить комментарий
База данных сайта разрослась, около 1 Гб. Сайт на dle 11.2. Посещаемость небольшая около 3 к сутки. В логе медленных запросов такая штука -
# User@Host: User[User] @ localhost []
# Query_time: 6.499257 Lock_time: 0.000030 Rows_sent: 1 Rows_examined: 1471843
SET timestamp=1533547256;
SELECT COUNT(*) as count FROM dle_post WHERE approve=1 AND allow_main=1;
Это обращение к главной странице, там ничего особенного, просто список постов отсортированных по дате.
collation-server = utf8_general_ci
character-set-server = utf8
local-infile=0
innodb_file_per_table = 1
pid-file = /var/run/mysqld/mysqld.pid
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
bind-address = 127.0.0.1
max_allowed_packet = 128M
log-slow-queries=/tmp/slow_queries.log
long_query_time=5
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
Сам сервер - KS-11 Server - Intel W3520 - 16GB DDR3 ECC 1333 MHz - SoftRaid 2x2To SATA
Вам необходимо грамотно настроить ваш сервер, как минимум mysql точно.
Стандартные настройки хорошо, но они не подходят для реальных задач.
mysqltuner вам в помощь, но делайте всё с умом, не надо ставить огромные значения,
также как и не всегда стоит слепо следовать рекомендациям тюннера.
Далее ваш SELECT затронул 1.4млн строк, это не есть хорошо.
Проверьте его через EXPLAIN, убедитесь чтобы запрос использовал индексы.
Если индексов в базе нет, то обязательно добавьте их где не хватает.
Точно так-же и с остальными медленными запросами.
Индекс тут бессмысленный, т.к. approve и allow_main скорее всего флаги, кардиналити у них будет очень низкий.
Ваш вариант - кешировать данные, или если точность не кретична - ходить в информационные таблицы.
А еще лучше выкинуть этот count вовсе... наверняка никому не нужный счетчик непоймичего.
У меня тоже есть такой тяжелый каунт на главной, я кеширую этот запрос через мем кеш, и проблема пропала.
Еще как вариант - изменитить логику вывода - выводить список постов с сортировкой не по дате, а по ID, на ID по идее должен быть первичный ключ и будет в разы быстрее.
он и так использует PK для подсчета, проблема в том, что у него WHERE, а без table scan на низком кардиналити у индекса будет перформанс ещё хуже, вот прямо сходил в доку и взял оттуда:
Этот запрос вряд ли отвечает за сам список постов, скорее за пагинатор, который определяет лимиты для последней страницы. Его только кешировать можно. Можно ещё повесить колонку с рандомным uuid, и на неё индекс, где WHERE условия будут совпадать. И потом по ней делать COUNT, но это костыль и так делать не надо. Лучше кешировать, да хоть в файл, и то будет быстрее 6 секунд, не говоря уже о memcached/redis.
Вобщем был у меня сервер уже с настроенным my.cnf -
collation-server = utf8_general_ci
character-set-server = utf8
local-infile=0
innodb_file_per_table = 1
pid-file = /var/run/mysqld/mysqld.pid
datadir=/var/lib/mysql
socket=/var/lib/mysql/mysql.sock
user=mysql
# Disabling symbolic-links is recommended to prevent assorted security risks
symbolic-links=0
bind-address = 127.0.0.1
max_allowed_packet = 128M
log-slow-queries=/tmp/slow_queries.log
long_query_time=5
key_buffer_size= 2048M
## Cache
thread-cache-size = 16
table-open-cache = 1024
table-definition-cache = 1024
query-cache-size = 16M
query-cache-limit = 512K
## Per-thread Buffers
sort-buffer-size = 128K
read-buffer-size = 128K
read-rnd-buffer-size = 128K
join-buffer-size = 256K
#net_buffer_length = 2K
#thread_stack = 128K
## Temp Tables
tmp-table-size = 16M
max-heap-table-size = 16M
## Networking
back-log = 100
max-connections = 32
max-connect-errors = 10000
max-allowed-packet = 16M
interactive-timeout = 30
wait-timeout = 30
### Storage Engines
default-storage-engine = MyISAM
#default-storage-engine = InnoDB
#innodb = FORCE
#skip-innodb
## MyISAM
key-buffer-size = 16M
myisam-sort-buffer-size = 4M
## InnoDB
#innodb-buffer-pool-size = 1M
#innodb-log-buffer-size = 1M
#innodb_additional_mem_pool_size= 1M
#innodb-log-file-size = 100M
#innodb-file-per-table = 1
#innodb-open-files = 300
#innodb_flush_method = O_DIRECT
## Replication
server-id = 1
#log-bin = /var/lib/mysqllogs/bin-log
#relay-log = /var/lib/mysqllogs/relay-log
relay-log-space-limit = 16G
expire-logs-days = 7
#read-only = 1
#sync-binlog = 1
#log-slave-updates = 1
#binlog-format = STATEMENT
#auto-increment-offset = 1
#auto-increment-increment = 2
[mysqld_safe]
log-error=/var/log/mysqld.log
pid-file=/var/run/mysqld/mysqld.pid
тупо скопировал и все залетало)
Залетало у вас из-за
которое на MySQL 8.0.3 уже не прокатит. да и в целом, конфиг такой себе.
обычно query_cache включают, и если на реальном workload он помогает, тогда его оставляют. но помогать он может только при убогом дизайне приложения. когда у вас есть запись, query_cache сбрасывается, а т.к. его фронтенд работает в 1 поток, то легко наткнуться на блокировку мьютексов. Другими словами, если у вас на 1000 чтений 1 запись - вам это поможет. Если у вас 1 запись на 50-100 чтений - может только усугубить.
И да, у вас сейчас конфиг заточен скорее под myisam. Если у вас innodb - можно по лучше потюнить.
И наверное с постраничной навигацией?
Также у вас таблицы в innodb или myisam? Если первое то он туго COUNT кушает, а вот с myisam не должно быть проблем.
Но как указали выше если у вас innodb то у вас вообще нет настроек под него.
Также у вас как идёт наполнение сайта? Автоматически т.е. парсер работает?
И наверное с постраничной навигацией?
Также у вас таблицы в innodb или myisam? Если первое то он туго COUNT кушает, а вот с myisam не должно быть проблем.
Но как указали выше если у вас innodb то у вас вообще нет настроек под него.
Также у вас как идёт наполнение сайта? Автоматически т.е. парсер работает?
Таблицы myisam, наполнения автоматического нет. Пока полет нормальный, будем решать проблемы по мере их поступления.
У меня тоже есть такой тяжелый каунт на главной, я кеширую этот запрос через мем кеш, и проблема пропала.
Не всегда кеширование помогает, тут нужно с самим запросом что-то делать. У меня было что-то похожее с использованием мемкеша, так всё валилось из-за времени. Пришлось сильно оптимизировать сам запрос, и только тогда заработало как положено.