Pull to refresh

Обзор движка Falcon в mySQL

Reading time7 min
Views3.4K
Original author: Vadim
Несмотря на то, что ещё в середине июня 2008 года Джим Старки (в тот момент глава команды, работающей над движком Falcon) покинул проект, и вообще на весьма туманные перспективы использования данного движка в следующих версиях mySQL, хотелось бы поделиться тем, что разработчики хотели в нём реализовать.

Итак, некоторые особенности Falcon (далее вольный перевод):
  • Отсутствие spinlock'ов. Falcon не использует spinlock'и. Он использует свой собственный механизм блокировок, заставляющий операционную систему переходить в режим ожидания, если ресурс недоступен. Посмотрим, к чему это приведёт, но я полагаю, что в условиях ОС с поддержкой нескольких процессоров при некоторых типах блокировок, когда может быть несколько конфликтов, будет необходимо использовать spinlock'и. Сейчас уже даже в ноутбуки устанавливается несколько процессоров, поэтому можно забыть о ситуации, когда spinlock в пустую тратит процессорное время единственного CPU без практической выгоды. В тоже время spinlock'и нужно использовать с умом.
  • Кэширование строк. Не может не радовать факт, что Falcon позволяет кэшировать отдельные строки таблиц, т.к. это означает, что в одинаковом объёме оперативной памяти можно сохранить большее количество данных. Вам может понадобиться сохранить в кэш только одну строку из страницы объёмом 8-16 КБ, однако кэширование на уровне страниц вынуждает сохранять всю страницу целиком; то есть если Вам потребуется поместить в кэщ 1000 100-байтовых строк, находящихся каждая на новой странице, в кэш, то с Falcon'ом Вам потребуется выделить всего лишь 100 КБ вместо 8-16 МБ. На практике же существуют специальные методики, позволяющие оптимизировать постраничное кэширование, поэтому в реальности выигрыш будет несколько меньше.
  • Вместо фиксированного объёма кэша — диапазон. Незначительное изменение, к тому же неоднозначное. Врят ли Вы сможете увидеть, что Falcon использует минимальный или максимальный пределы объёма памяти, выделяемые под кэш, а не какое-то фиксированное значение. Если у меня есть 8 GB оперативной памяти, и я решил выделить под кэш 4 GB, то какое мне дело как mySQL будет управлять этими гигабайтами? И какой диапазон в этом случае нужно задать, чтобы кэширование было максимально эффективным — 3 ГБ или может быть 3.8 ГБ? В чём разница? Не будет ли чистка памяти запускаться слишком часто, если я задам близкие друг к другу минимальное и максимальное значения? Документация на этот счёт ничего конкретного не говорит.
  • Небольшое количество настроек. Возможно, это несколько противоречит предыдущему пункту, но давайте посмотрим на это с точки зрения экспериментатора, а не обычного пользователя. Я бы хотел иметь большее количество настроек, чтобы настроить поведения базы данных под свои нужды. Я люблю принцип «не требует администрирования», и я бы хотел, чтобы база данных делала всё за меня, но для начала она должна доказать, что может это сделать лучше меня, а достичь этого можно только дав сравнить производительность системы на двух конфигурациях: автоматической и той, что я сделал сам собственными руками. До сих пор я не видел автоматических конфигураций, которые могли бы подойти под все режимы нагрузки на сервер — они могут прекрасно справляться с «типичными» режимами, но быть неэффективными при работе в нестандартных режимах, что в случае mySQL происходит довольно часто.
  • Небольшие индексы. Индексы, занимающие мало места — это здорово. С другой стороны огромные индексы — это залог высокой производительности InnoDB. Поэтому на самом деле нужно будет посмотреть, насколько «небольшими» получатся индексы и насколько от это пострадает (или насколько выиграет) производительность системы. В релизе, на котором мы тестировали Falcon, команда «SHOW TABLE STATUS» не показывает размер индекса, поэтому оценить это нововведение затруднительно.
  • Отсутствие команды «USING INDEX». Falcon вынужден всегда просматривать содержимое строки, даже если выборка извлекает только данные, содержащиеся в индексе. Я считаю это огромной проблемой, т.к. «покрывающие индексы» (covering index) позволяют существенно повысить производительность многих запросов.
  • Упорядоченное чтение данных. В отличает от других движков, которые читают данные в соответствии с проходов по индексу, Falcon может оптимизировать этот процесс, пройдя сначала весь индекс (а может быть и по объединению индексов), и только после этого считывая уже упорядоченные данные. Это может сильно помочь, если Вам приходятся выбирать большое количество данных из таблицы. Однако я считаю, что такая возможность должна быть вынесена выше уровня движков mySQL (Storage Engine level) — чтение строк в порядке их физического расположение может быть реализовано для большинства типов движков, и уж точно — для MyISAM и InnoDB. Помню, что подобные планы звучали некоторое время назад, но делается ли что-либо в этом направлении мне не известно.
  • Отсутствие поддержки кластеризации индекса. В отличие от InnoDB Falcon не группирует данные ни по Primary-индексу, ни по каким-либо другим индексам. В каких-то случаях это хорошо, в каких-то — плохо. Многие уже существующие приложения опираются на данную особенность InnoDB, поэтому данную особенность скорее можно к отрицательной стороне нового движка. По-моему данную возможность следовало бы сделать необязательной (например так, как это уже сделано в InnoDB — Вы можете создать скрытый Primary-ключ), однако такая возможность была бы плохо портируемой, т.к. Вам пришлось бы удалять Primary-ключ и т.д. В некоторых презентациях утверждается, что Falcon не нуждается в кластеризации индексов, т.к. использует специальную оптимизацию при их чтении. Однако это не тот случай. Если Вам необходимо прочитать небольшую часть Primary-ключа в InnoDB, то mySQL просмотрит всего несколько страниц, в то время как Falcon'у (в случае, если строки были добавлены в разное время и «раскиданы» по индексу) понадобится прочитать значительно больше страниц. К примеру, подумайте о типичных случаях применения кластеризации в InnoDB — почтовые ящики пользователей, в таблице с кластеризованным ключом (user_id,message_id).
  • Сжатие строк. В Falcon реализован механизм быстрого сжатия данных в строках; к примеру, он использует ровно столько байт для значения типа integer, сколько требуется (а не сколько отведено для максимума), не сохраняет значения в колонке, если оно равно значению по умолчанию и т.д. Это замечательное нововведение, хотя и может вызвать некоторые трудностни: например, если Вы захотите поменять значение по умолчанию у какого-либо столбца, то Falcon должен будет перестроить всю таблицу, а не просто изменить её мета-данные (впрочем, эта возможность тоже не реализована в mySQL). Будет очень интересно посмотреть на соотношение «производительность — степень сжатия» у Falcon относительно прозрачного gzip-сжатия, реализованного в InnoDB.
  • Табличная область уровня базы данных. Как Вы уже могли заметить в текущем релизе, Falcon создаёт отдельную табличную область и собственные логи для каждой базы данных. При стандартном mySQL подходе с созданием отдельной директории для каждой таблицы это может вызвать определённые трудности: если транзакция порождает несколько баз данных, то при её фиксации (т.е. при commit'е) Вам нужно будет обновить несколько логов. К тому же для синхронизации фиксаций транзакции в нескольких базах данных нужно будет либо использовать XA-транзакции (что весьма ресурсоёмко), либо может возникнуть ситуация, когда транзакция была зафиксирована в одной базе, но не в другой. Ещё одна проблема заключается в том, что последовательные «снимки» сервера будут последовательными только в пределах базы данных, поэтому если Вы начнёте транзакцию, обращающуюся к базе A, а несколько позже к базе B, то в базе данных B Вы увидите строки, которые были добавлены/обновлены уже после того, как началась транзакция.
  • Режимы изоляции. В настоящее время Falcon поддерживает очень ограниченный набор изоляций запросов (в том числе не поддерживает запросы вида SELECT FOR UPDATE). Движок Falcon использует Оптимистичную модель блокировок при конкурентном доступ, что может повлечь за собой проблемы в условиях работы сервера с большим количеством UPDATE-запросов, которые вынуждены будут ждать освобождения блокировки на уровне строки. К тому же сейчас возникает забавная ситуация, когда движок ожидает окончания транзакции с UPDATE-запросом, после выполнения которой всё равно аварийно останавливается с ошибкой «ERROR 1020 (HY000): Record has changed since last read in table ‘t’» («Запись была изменена с момента последнего чтения таблицы»). Нельзя сказать, что такое поведение движка хуже, чем в случае с InnoDB, оно — другое, и это нужно учитывать при разработке приложений на основе Falcon. Документации по данному вопросу также маловато.
  • Нет защиты от частичной записи в страницу. Это означает, что если запись в данную страницу была не атомарной, т.е. при изменении какой-то части страницы другая её часть осталась старой, то таблица может быть неисправимо повреждена. Именно поэтому InnoDB использует буфер двойной записи (прим.: InnoDB перед записью страниц в файл сначала записывает их в смежный участок табличной области, поэтому после сбоя при восстановлении InnoDB сможет найти копию данных в смежном участке). Джим не считает это существенной проблемой, хотя я не один раз сталкивался с ней при использовании движка InnoDB до введения в него буфера двойной записи. Разговаривая с разработчиками PostgreSQL и Oracle я пришёл к выводу, что все они в курсе данной проблемы и имеют собственные методы борьбы с ней, поэтому я не слишком понимаю, почему Джим в неё не слишком верит.
  • Данные на диске меняются только после фиксации транзакции. Движок InnoDB меняет данные в файлах сразу после того, как была отдана такая команда, Falcon же — только после commit'а. У этого момента есть как положительные стороны (например, отсутствие долгих откатов при больших транзакциях), так и отрицательные (повышенные требования к объёму оперативной памяти). Я согласен, что большинство транзакций — небольшие, однако в случае, например, пакетной обработки чего-либо Вам может понадобится либо увеличить объём памяти, либо переписать запросы так, чтобы фиксация транзакций происходила чаще.
  • Оптимизация работы с данными типа BLOB. Джим любит BLOB'ы как своих собственных детей, поэтому Falcon оптимизирован для работы с ними, например, реализована прямая запись BLOB в базу данных. Будет интересно посмотреть на результаты этой оптимизации в реальности.

Ещё один интересный момент, о котором я не нашёл никакой информации в документации — обработка фрагментации: что происходит при обновлении строк — обновлённые строки хранятся в том же месте или в новом? Разделяются ли строки на несколько частей, как это происходит в MyISAM, или всегда хранятся компактно? Это весьма важные вопросы относительно I/O производительности движка.

PS от переводчика: к настоящему времи движок находится в разработке уже более 4 лет, а «бета» ещё настолько сырая, что Falcon проигрывает практически по всем тестам не только своему «прародителю» InnoDB, но и MyISAM. В то же время движок Maria развивается куда быстрее (этот движок является развитием MyISAM, а не InnoDB, хотя и является полностью транзакционным и обладает всеми свойствами ACID), поэтому вовсе не понятно, зачем mySQL разрабатывает столько движков одновременно, которые фактически равны друг другу по возможностям.
Tags:
Hubs:
+2
Comments6

Articles

Change theme settings