Профилирование запросов Mnesia

Наша Mnesia DB работает медленно, и мы думаем, что она должна быть несколько быстрее.

Итак, нам нужно профилировать его и выяснить, что происходит.

Есть несколько вариантов, которые предлагают сами:

  • запустите fprof и посмотрим, куда идет время.
  • запустите cprof и посмотрите, какие функции называются много.

Однако они являются довольно стандартными инструментами стиля контроля производительности. Вопрос в том, как я действительно выполняю профилирование запросов - какие запросы занимают самые длительные периоды. Если бы мы были магазином Oracle или MySQL, мы бы просто запускали профилировщик запросов, который возвращал бы те запросы, которые занимали много времени. Это не инструмент, который, как представляется, доступен для Mnesia.

Итак, вопрос:

  • какие существуют методы для профиля Mnesia
  • Какие существуют инструменты для профилирования Mnesia - нет, я думаю, но докажу, что я не прав:)
  • как вы профилировали свои запросы и оптимизировали установку базы данных mnesia.

Расширение в свете обсуждения

Одной из проблем с fprof в качестве инструмента профилирования является то, что он сообщает только о конкретном запросе, на который вы смотрите. Поэтому fprof говорит мне, что X медленный, и я настраиваю его, чтобы ускорить его. Тогда, низко и созерцать, операция Y (которая была достаточно быстрой) теперь является собакой медленной. Поэтому я прорабатываю Y и понимаю, что способ быстро сделать Y - сделать X медленным. Поэтому я заканчиваю серию двусторонних компромиссов...

То, что мне действительно нужно , - это способ управления многосторонними компромиссами. Теперь у меня есть 2 метрических сбрасывания фактических действий пользователя, которые я могу воспроизвести. Эти журналы представляют собой то, что я хотел бы оптимизировать.

"Собственный" анализатор запросов в базе данных SQL будет иметь возможность профилировать структуру операторов SQL, например, всех операторов с формой:

SELECT [fieldset] FROM [table] WHERE {field = *parameter*}, {field = *parameter*}

и говорят, что 285 запросов этой формы занимали в среднем 0,37 м для запуска

Магические ответы - это когда говорится: 17 запросов этой формы заняли 6.34s для выполнения и выполнили полное сканирование таблицы в таблице X, вы должны поместить индекс в поле Y

Когда у меня есть результат, подобный этому, через репрезентативный набор пользовательских действий, я могу начать рассуждать о компромиссах в раунде и разработать тестовый шаблон.

Тестовый шаблон будет выглядеть примерно так:

  • активность X будет делать запросы A, C и C быстрее, но запросы E и F медленнее,
  • проверить и измерить
  • затем одобрить/отклонить

Я использую Erlang достаточно долго, чтобы "знать", что нет такого анализатора запросов, как это, я бы хотел знать, как другие люди (у которых была эта проблема) "причина" в оптимизации mnesia.

Ответы

Ответ 1

Я откинулся назад, потому что я не очень разбираюсь ни в Эрланге, ни в Mnesia, но я знаю много о настройке производительности, и из обсуждения пока это звучит довольно типично.

Эти инструменты fprof и т.д. звучат как большинство инструментов, которые получают свой фундаментальный подход от gprof, а именно: инструменты, подсчет вызовов, выборку счетчика программ и т.д. Немногие имеют долгое время изучали основы этой практики. Ваши разочарования звучат типично для пользователей таких инструментов.

Здесь известен менее известный метод описанный здесь. Он основан на принятии небольшого количества (10-20) выборок состояния программы в случайные моменты времени и понимания каждого из них, а не суммирования. Как правило, это означает проверку стека вызовов, но вы также можете изучить другую информацию. Существуют разные способы сделать это, но я просто использую кнопку паузы в отладчике. Я не пытаюсь получить точное время или количество вызовов. В лучшем случае это косвенные подсказки. Вместо этого я прошу каждого образца "Что он делает и почему?" Если я нахожу, что он выполняет определенную деятельность, например, выполняя X-запрос, где он ищет ответ типа y для цели z, и он делает это на более чем одном образце, тогда доля выборок, которые он делает, является грубая, но достоверная оценка того, какая часть времени она делает. Скорее всего, это то, над чем я могу что-то сделать, и получить хорошее ускорение.

Вот пример использования метода.

Ответ 2

Поскольку запросы Mnesia - это просто функции erlang, я бы предположил, что вы можете профилировать их так же, как и профиль вашего собственного кода erlang. http://www.erlang.org/doc/efficiency_guide/profiling.html#id2266192 содержит дополнительную информацию о доступных инструментах профилирования erlang.

Обновление. В качестве теста я запускал это дома на экземпляре тестовой mnesia и с помощью fprof для отслеживания запроса mnesia qlc возвращал вывод, образец которого я включаю ниже. Таким образом, он определенно содержит больше информации, чем просто запрос.

....
{[{{erl_lint,pack_errors,1},                      2,    0.004,    0.004}],     
 { {lists,map,2},                                 2,    0.004,    0.004},     %
 [ ]}.

{[{{mnesia_tm,arrange,3},                         1,    0.004,    0.004}],     
 { {ets,first,1},                                 1,    0.004,    0.004},     %
 [ ]}.

{[{{erl_lint,check_remote_function,5},            2,    0.004,    0.004}],     
 { {erl_lint,check_qlc_hrl,5},                    2,    0.004,    0.004},     %
 [ ]}.

{[{{mnesia_tm,multi_commit,4},                    1,    0.003,    0.003}],     
 { {mnesia_locker,release_tid,1},                 1,    0.003,    0.003},     %
 [ ]}.

{[{{mnesia,add_written_match,4},                  1,    0.003,    0.003}],     
 { {mnesia,add_match,3},                          1,    0.003,    0.003},     %
 [ ]}.

{[{{mnesia_tm,execute_transaction,5},             1,    0.003,    0.003}],     
 { {erlang,erase,1},                              1,    0.003,    0.003},     %
 [ ]}.

{[{{mnesia_tm,intercept_friends,2},               1,    0.002,    0.002}],     
 { {mnesia_tm,intercept_best_friend,2},           1,    0.002,    0.002},     %
 [ ]}.

{[{{mnesia_tm,execute_transaction,5},             1,    0.002,    0.002}],     
 { {mnesia_tm,flush_downs,0},                     1,    0.002,    0.002},     %
 [ ]}.

{[{{mnesia_locker,rlock_get_reply,4},             1,    0.002,    0.002}],     
 { {mnesia_locker,opt_lookup_in_client,3},        1,    0.002,    0.002},     %
 [ ]}.

{[ ],
 { undefined,                                     0,    0.000,    0.000},     %
 [{{shell,eval_exprs,6},                          0,   18.531,    0.000},      
  {{shell,exprs,6},                               0,    0.102,    0.024},      
  {{fprof,just_call,2},                           0,    0.034,    0.027}]}.

Ответ 3

Предложение Майка Данлави напоминает мне о redbug, который позволяет вам выбирать вызовы в производственных системах. Подумайте об этом как о удобном в использовании erlang:trace, который не даст вам достаточно веревки, чтобы повесить вашу производственную систему.

Использование чего-то вроде этого вызова должно дать вам много трасс стека, чтобы определить, откуда вы вызываете транзакции mnesia:

redbug:start(10000,100,{mnesia,transaction,[stack]}).

Невозможно получить длительность вызова для этих трасс.

Если вы организовали все поиски mnesia в модулях, которые экспортируют api для их выполнения, вы также можете использовать redbug для получения частоты вызовов только для определенных запросов.