Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1 2
Как-то даже не задумывался, блокируются ли таблицы MyISAM при вставке и обновлении данных, но я так понимаю, что всё же блокируются?
Обратил внимание, что селекты не могут достучаться до базы, глянул в процессы - там туча апдейтов валит. Апдейтов и инсертов бывает и по несколько штук в секунду, а среднее нормальное время выполнение селектов - 1.5-3 секунды. Вот как они там в это время доступом делятся - ума не приложу. Приоритет у апдейтов понижен. Подскажите пилюли от сей болезни.
Ещё как-то заметил торможение базы в арифметической прогрессии в зависимости от продолжительности работы. Через сутки после рестарта, запросы выполняются раза в 3-4 дольше, при чём такое наблюдается только на активной таблице. Никак не могу понять с чем это связано По выделению памяти в конфиге уже такие большие цифры поставил, что поднимать их совесть не позволяет Хелпните плз...
Отредактированно Neval (17.03.2008 17:03:09)
Неактивен
Блокируются. В MyISAM table-based locking. Как лечение можно преобразовать в INNODB. INSERT в конец таблицы можно ускорить с помощью concurrent_insert=1 http://dev.mysql.com/doc/refman/5.1/en/ … serts.html
Смотрите SHOW STATUS когда тормозит; важно какие именно кэши заполняются.
Неактивен
InnoDB не подходит из-за скорости выборок. В моём случае это самый важный аргумент.
Ок, спасибо за направление, буду пробовать.
Неактивен
Попробуйте использовать запросы на изменение данных с модификатором LOW_PRIORITY - тогда запросы на выборку будут обладать более высоким приоритетом
Неактивен
Попробуйте использовать запросы на изменение данных с модификатором LOW_PRIORITY
У меня сервер стартует с этим параметром + ещё опцию в SQL выполняю при каждом коннекте.
Вот сейчас запросы выполняются примерно в 2.5 раза дольше, чем после старта сервера. Сервер работает всего 15 часов.
rgbeast написал:
Смотрите SHOW STATUS когда тормозит; важно какие именно кэши заполняются.
Глянул статус. Много переменных, много больших значений... Привожу некоторые, имхо, нужные. Разъясните где что плохо:
Created_tmp_files 17
Created_tmp_tables 7
Handler_read_rnd_next 125
Handler_write 251
Key_blocks_not_flushed 917
Key_blocks_unused 199599
Key_blocks_used 260955
Key_read_requests 153251297
Key_reads 617834
Key_write_requests 5820343
Key_writes 1477956
Open_files 566
Open_tables 471
Qcache_free_blocks 428
Qcache_free_memory 132655904
Qcache_hits 13905
Qcache_inserts 25489
Qcache_lowmem_prunes 0
Qcache_not_cached 49509
Qcache_queries_in_cache 1295
Qcache_total_blocks 3095
Questions 1031795
Table_locks_immediate 669007
Table_locks_waited 359473
Threads_cached 8
Threads_connected 13
Threads_created 34
Threads_running 13
Также сразу приведу вырезку из конфига:
skip-locking
key_buffer_size = 512M
max_allowed_packet = 16M
table_cache = 2K
sort_buffer_size = 256M
join_buffer_size = 256M
net_buffer_length = 16K
read_buffer_size = 16M
read_rnd_buffer_size = 64M
myisam_sort_buffer_size = 512M
ft_min_word_len = 2
tmp_table_size = 128M
query_cache_size = 128M
query_cache_limit = 4M
bulk_insert_buffer_size = 64M
myisam_max_sort_file_size = 10G
max_connection = 512
thread_cache_size = 16
Цифры ставил в основном из соображений красных значений при показе текущего состаяния базы через phpMyAdmin + сравнивал с my-large.ini.
Понимаю, могут быть кривые идексы с запросами, но торможение-то по идее не должно быть вот так, в зависимости от продолжительности работы сервера :\
Неактивен
Плохо вот это:
Table_locks_immediate 669007
Table_locks_waited 359473
Около трети апдейтов не получают lock сразу.
Еще интересно
show status like '%select%';
show status like 'com%';
Вроде у Вас кэши незаполнены. Попробуйте загрузить индексы в кэш напрямую для каждой таблицы LOAD INDEX INTO CACHE mytable; как написано в статье (это уменьшит фрагментацию):
http://sqlinfo.ru/articles/info/3.html
Неактивен
Да, по состоянии базы в phpMyAdmin я видел красные цифры в описании аля "Около трети апдейтов не получают lock сразу", но не знаю с чем это может быть связано. Если порассуждать, стандартный запрос, используемый в проекте занимает 1.5-3 секунды, а значит и для апдейта нужно дожаться его выполнения, как я понимаю?
Вот результат show status like 'com%':
Com_select 2
Com_set_option 4
Com_show_charsets 1
Com_show_collations 1
Com_show_databases 1
Com_show_grants 1
Com_show_status 1
Com_show_variables 3
Compression OFF
Все остальные значения равны нулю.
show status like '%select%':
Select_full_join 0
Select_full_range_join 0
Select_range 0
Select_range_check 0
Select_scan 7
Попробуйте загрузить индексы в кэш напрямую для каждой таблицы LOAD INDEX INTO CACHE mytable; как написано в статье
У меня по данной статье ещё ранее возник вопрос, вот как раз самое время его задать)))
Этот индекс нужно загружать постоянно при каждом коннекте? Если да, то не будет ли это излишне загружать базу, при наличии 50 одновременных коннектов?
Неактивен
Вы привели статистику сразу после перезагрузки сервера. Приведите ее после того, как сервер поработает какое-то время.
Загружать ключи один раз после каждой перезагрузки mysql-сервера. Можно написать sql-скрипт и вписать его в my.cnf init-file=/путь/к/файлу.sql
Неактивен
rgbeast написал:
INSERT в конец таблицы можно ускорить с помощью concurrent_insert=1
Всегда и было concurrent_insert=1.
Неактивен
rgbeast написал:
Вы привели статистику сразу после перезагрузки сервера. Приведите ее после того, как сервер поработает какое-то время.
Я тоже так сначала подумал, ибо цифры маленькие, но это действительно после 16ти часов работы. Хотя сравнил с только-что запущенным сервером, все значения (com% и %select%) те же.
rgbeast написал:
Загружать ключи один раз после каждой перезагрузки mysql-сервера. Можно написать sql-скрипт и вписать его в my.cnf init-file=/путь/к/файлу.sql
Спасибо, сейчас сделаю.
Неактивен
Выполните:
SHOW GLOBAL STATUS LIKE '%select%';
SHOW GLOBAL STATUS LIKE 'com%';
Предыдущий запрос давал статистику сессии
Неактивен
ммм, дейсвительно... Ок, вечерком тогда отпишусь, когда тормоза начнутся
А такой вопрос.. а можно ли создать репликацию (синхронизацию) баз в пределах одного физического сервера?
Я так понимаю, в моём случае репликация поможет, но сервер пока только один)))
Неактивен
варианты
1. запустить два mysqld на одной машине на разных портах и настроить репликацию - учитывайте, что она не будет синхронной, UPDATE слейва будет запаздывать и, кроме того, все UPDATE будут выполняться на обоих серверах
2. перепроектировать приложение, чтобы SELECT не делался из той таблицы, в которую идет UPDATE (опять же не будет полной актуальности), например для SELECT можно использовать MEMORY-таблицу
Неактивен
А первый вариант присутствует в ситуации с репликацией на двух серверах?
Второй вариант интересный. Я так понимаю, это должна быть копия таблицы, в которую идут апдейты... Но таблица не маленькая, сейчас в ней уже 4.2М записей общим объёмом на 350Мб данных. На сколько реально хранить столько данных постоянно в памяти? К тому же, это далеко не лимит сей таблицы.
Актуальность 2х минут - не критична, 15 минут - это уже критично.
Неактивен
Репликация - это фактически тиражирование апдейтов от мастера на слейвы. Апдейты выполняются сначала на мастере, а затем реплицируются на слейвы, задержка сама по себе не большая (миллисекунды), но учитывая Вашу ситуацию апдейты могут и на слейве выстроиться в очередь.
Посмотрите, можете ли Вы себе позволить просто раз в 10 минут пересоздавать MEMORY-таблицу.
DROP TABLE mem_tbl;
CREATE TABLE mem_tbl ENGINE=MEMORY SELECT * from tbl;
Посмотрите сколько памяти съест (память все-таки недорогая, можно докупить несколько гигов).
Насколько инфа в таблице новая? Можно ли часть инфы, ставшей архивом и не подлежащей изменению вынести в отдельную таблицу?
Неактивен
Сейчас присутствует торможение на 70% примерно, вот статусы:
Select_full_join 0
Select_full_range_join 0
Select_range 207
Select_range_check 0
Select_scan 229
=====
Com_insert_select 0
Com_change_db 254
Com_select 583
Com_set_option 313
Com_show_binlog_events 0
Com_show_binlogs 15
Com_show_charsets 27
Com_show_collations 27
Com_show_databases 27
Com_show_grants 11
Com_show_open_tables 1
Com_show_tables 16
Com_show_variables 94
Com_update 4596
Вижу много апдейстов по последнему значений. Что ещё здесь критично?
Неактивен
Может и нормально, а может запросы SELECT слишком убойные. Еще попробуйте OPTIMIZE TABLE имя_таблицы
Innodb точно не поможет? Соотношение UPDATE/SELECT явно не в пользу SELECT.
http://dev.mysql.com/doc/refman/5.1/en/ … lect_range
Select_range
The number of joins that used ranges on the first table. This is normally not a critical issue even if the value is quite large.
Select_scan
The number of joins that did a full scan of the first table.
Неактивен
rgbeast написал:
Посмотрите, можете ли Вы себе позволить просто раз в 10 минут пересоздавать MEMORY-таблицу.
DROP TABLE mem_tbl;
CREATE TABLE mem_tbl ENGINE=MEMORY SELECT * from tbl;
Примерно через 5 секунд получаю ответ: #1114 - The table 'mem_tbl' is full. Чё-нибудь увеличить в конфиге?
rgbeast написал:
Насколько инфа в таблице новая? Можно ли часть инфы, ставшей архивом и не подлежащей изменению вынести в отдельную таблицу?
Скажем там, архивной инфы нет, вся актуальная и запрашиваемая, но вот поля апдейтов задумываюсь вынести в отдельную таблицу.
Сейчас за один апдейтовый запрос изменяется несколько десятков записей по некоторым условиям. Но если апдейтить эти поля в другой таблице, то это добавит очень много селектов на текущую, чтобы выявить ПК каждой нужной записи.
Неактивен
rgbeast написал:
Может и нормально, а может запросы SELECT слишком убойные.
Селекты не кислые, джоины 6-8 таблиц с группировками. Да и с индексами ещё не полностью определился. Я просто не могу понять почему скорость базы замедляется в арифметической прогрессии.
rgbeast написал:
Еще попробуйте OPTIMIZE TABLE имя_таблицы
Раз в сутки делаем
rgbeast написал:
Innodb точно не поможет? Соотношение UPDATE/SELECT явно не в пользу SELECT.
Сложно сказать о соотношении. Большое количество планируется и того и другого, можно сказать, что 50/50. Да и сами селекты, как я писал выше, не простые.
Сейчас имеем
Select_range 269
Select_scan 579
Неактивен
Примерно через 5 секунд получаю ответ: #1114 - The table 'mem_tbl' is full. Чё-нибудь увеличить в конфиге?
max_heap_table_size=1G
Сейчас за один апдейтовый запрос изменяется несколько десятков записей по некоторым условиям. Но если апдейтить эти поля в другой таблице, то это добавит очень много селектов на текущую, чтобы выявить ПК каждой нужной записи.
Может быть и лучше из-за разделения SELECT/UPDATE.
Оптимизация дело творческое
Неактивен
Добавил в конфиг
max_heap_table_size=1G
Теперь имею (на многих запросах) ответ:
#5 - Out of memory (Needed 67108836 bytes)
ну и есессно байты в каждом запросе свои.
Отсюда вопрос. Цифры из моего конфига я приводил, какие из них есть смысл уменьшить?
Неактивен
key_buffer используется только половина, можно уменьшить до 70% (правда попробуйте сначала загрузить все индексы с помощью LOAD KEY INTO CACHE)
query_cache вероятно можно отключить совсем, так как запросы уникальные, а таблицы меняются, попробуйте
Установите tmp_table_size = 8M - mysql юзает память для временных таблиц, если таблица влезает в min(max_heap_table_size, tmp_table_size). По умолчанию heap - 16M, tmp_table - 32M. Вы увеличили heap, следовательно лимит временных таблиц вырос с 16 до 32 мегов. Вероятно временные таблицы не спасают Ваши запросы все равно.
http://dev.mysql.com/doc/refman/5.1/en/ … table_size
Обратите внимание, что некоторые буфферы выделяются для каждого подключения, поэтому цифры ниже указаны несколько щедро (64M может хватить)
sort_buffer_size = 256M
join_buffer_size = 256M
myisam_sort_buffer_size = 512M
Неактивен
rgbeast написал:
правда попробуйте сначала загрузить все индексы с помощью LOAD KEY INTO CACHE
В том-то и дело, что если загрузить индексы, то начинается ругаться на отсутствие памяти)))
Сейчас проделаю всё остальное.
Неактивен
Кстати, буфер в конфиге, в том числе сессионный не приводит к выделению памяти, пока она не потребуется. Скажем myisam_sort_buffer_size = 512M может ни к чему не приводить, но потом найдется запрос, который догадается как использовать этот буффер и он его использует с результатом No memory.
Если память узкое место, проще всего купить еще 2-4 гига. Время программиста дорого, проще купить железо.
Неактивен
Всё-таки после применения LOAD KEY INTO CACHE, некоторые запросы не выполняются из-за нехватки памяти
Сейчас в конфиге имею такие записи:
skip-locking
key_buffer_size = 384M
max_allowed_packet = 16M
max_heap_table_size = 1G
table_cache = 2K
sort_buffer_size = 64M
join_buffer_size = 64M
net_buffer_length = 16K
read_buffer_size = 16M
read_rnd_buffer_size = 64M
myisam_sort_buffer_size = 64M
ft_min_word_len = 2
tmp_table_size = 8M
bulk_insert_buffer_size = 64M
myisam_max_sort_file_size = 10G
max_connection = 512
thread_cache_size = 16
Так, в общем, из данной дискуссии можно сделать выводы, что всё же апдейты нужно перенаправить на другую таблицу.
ЗЫ Сейчас на сервере установлено 4Гб памяти.
Отредактированно Neval (18.03.2008 14:43:57)
Неактивен
Страниц: 1 2