Читаем и пишем MyISAM напрямую
Автор: Раздел: MySQL
В недрах документации MySQL на я когда-то заметил упоминание о этом в возникнувшем случае, если употребляется MyISAM, возможно заполучить прирост в быстроты чтения из таблицы в 5-7 раз, если декламировать исходные из таблицы самостоятельно. Ми достаточно долго желалось испробовать данный факт и тут, наконец-то, около меня дошли руки до этого, дабы сие отведать. Что из данного вышло, читайте под катом
Какой-никакого типа данные мы станем читать из MyISAM? Формат MyISAM — сие, в самом деле, несколько форматов (точнее — немного форматов сохранения индексов и несколько типов хранения этих, для этих более общераспространенные — это fixed и dynamic). Мне было забавно осмотреть самый-самый простой вариант: когда матрица обладает прочную длину записи, не включает NULL полей и этот тип запросов, какой мы беремся испытывать — это несложной SELECT * FROM tbl WHERE (фактор) в отсутствие роли индексов и других таблиц (то, что именуется full scan). Для чего? Как правило, мной подвигал спорт энтузиазм. Не смотря на все это, итоги вышли недурными, по этой причине, вероятно, кто-то, помимо меня, захотит попробовать использовать этот способ на практике. Как будем декламировать? Сначало я разглядывал довольно множество альтернатив, как можно читать данные из MyISAM, в том числе и с применением индексов. Для чтения прямо из индексных файлов имеется довольно доброе детали в файле myisam.txt, который ранее разносился с отправными кодами MySQL, но теперь его можно отыскать, . Для програмки, какая желает читать MyISAM вместе с индексными текстурами, возможно, требуется брать значимую часть MySQL. Отлично, что это необходимо делать один раз . Я же буду осматривать standalone прибавление, какое не может зависеть от отправных кодов MySQL и не употребляет индексы, а только лишь читает .MYD комп.данные прямо, в самом несложном, fixed, формате строчек. Формат хранения в .MYD Формат хранения для различных структур MyISAM весьма хорошо описан тут: . Формат же для fixed строк так прост, что его можно привести напрямую в тексте заметки: 1) .MYD состоит из поочередно шкандыбающих строчек, и только из их. Безличный должностной данных в .MYD недостает 2) Около любой строчки есть заголовок, в котором записана данные об NULL-полях и флаг, сигнализирующий о том, что строчка удалена. Если NULL-полей недостает, то длина заголовка сочиняет 1 б три) В строчке поля идут в бинарном формате, в этом распорядке, в котором определены поля таблицы, с возвратным распорядком байт (little endian), без пробелов Для разных типов MySQL бинарное понятие различное, и оно хорошо представлено по гиперссылке выше Как читать из .MYD Предполагая, что вы беретесь читать данные из .MYD из програмки на слоге C, вот несколько нюансов из моей а не твоей осуществлении, какие затрагивают производительности: 1) если длина одной строки мала (скажем, 10 б), то и при долгосрочном использовании fread() стоит читать не по одной строчке, а, скажем, по сто — для моей программы это убыстрило чтение из файла неизвесно где в 2 раза 2) очень вероятно, доступ к раздельным полям станет невыровненным, поэтому, если ваша зодчество выделяется от x86 (пример, PPC), то не стоит употреблять последующую несложную конструкцию для того, чтобы выдернуть непонятно какое точное поле: *(int*)(ptr) (ptr — указатель на завязало поля, само поле, при этом, имеет тип int) Кроме этого, нужно обеспокоиться вопросами блокировки таблицы при истоке чтения (сие можно сделать с помощью LOCK TABLES tbl READ). Если этого не делать, то есть шанс нарваться на «нечистые» данные при чтении (до переоформленных вполовину строк, если не повезло). Если посмотреть с другой стороны, именно при подобном сценарии чтения из MyISAM можно достаточно невредно переступать блокировки и читать из таблицы в тот момент, когда тама некто строчит, имея минимум сторонных результатов. Вы нечто сообщали про запись? Правда, MyISAM с fixed форматом строк настолько прост, что мы можем самочки основывать таблицы для MySQL и заполнять их исходными. Неужели что, без индексов. Однако они необходимы далеко не всегда, а если они очень необходимы, то можно после просить MySQL досоздать их чрез ALTER TABLE. Как общеизвестно, таблицы MyISAM заключаются из три файлов: .frm, .MYI и .MYD. Мы видим, как саккумулировать .MYD. Осталось сгенерировать .frm и .MYI. Вы, вероятно, поспрашивайте: а для чего нам вобщем .MYI? Разве вслед за тем не сохраняются индексы (каких у нас не намечается)? На самом деле, там хранятся не только индексы. Про это чуток позднее. Наиболее простой метод сгенерировать .frm и .MYI — это предпринимать данные файлы у какого-то «донора», т. е., другой таблицы. У данной таблицы не должно быть индексов, и данная таблица обязана владеть текстуру, которая отвечает нашему .MYD файлу, или же MySQL почитать подобную таблицу не может . Если вы элементарно перекопируете .frm и .MYI файлы у отделанной таблицы и запишете в .MYD необходимые строчки, то, скорее всего, вы увидите, что MySQL считает, что в новой таблице держится 0 строк. Сие обязано навести нас на идеи, что в MyISAM всё не настолько просто . На самом же деле, есть один довольно популярный факт — в MyISAM таблицах есть информация о числе строк, которая искается в одном из полей текстуры этой таблицы. Осталось отыскать это поле и девало в шапке ! Как бы это ни было удивительно, это поле находится не в .frm файле, а в .MYI. Да, в том самом файле, в котором лежат «индексы». Вслед за тем же по совместительству лежит иная мета-информация, которая является специфичной для MyISAM и в .frm файл не пишется (.frm представляются всеобщими для многих вариантов таблиц). В пригнанном меньшей выше описании формата MyISAM есть описание MYI файлов. На самом деле, нам довольно скопировать только 2 поля в этом файле (для версии MySQL пятого.1): 1) state->state.records (увольнение относительно завязала файла — 0x1C, длина восьмой б, ровной распорядок байт (big endian), содержит всеобщее число строк кроме далёких) 2) state->state.data_file_length (смещение относительно начала файла — 0x44, длина 8 байт, прямой порядок байт (big endian), содержит габарит файла .MYD в б). В случае проблем с чтением «новых» таблиц стоит для начала испробовать, что вы не переписываете имеющийся таблицу, а основываете новоиспеченную. Если вы желаете вписать таблицу заместо престарелой — сначала нужно сделать DROP TABLE этой таблицы конкретно из MySQL, и только затем создавать данную таблицу по новой (дабы MySQL нечаянно не заюзал монета приоткрытых файлов). Иной вид — сделать FLUSH TABLE для этой таблицы и после этого вписывать туда новоиспеченные данные (сгодится, если вы поделаете APPEND к таблице). Значит так, если вы прочитали заметку до конца (и если вы видите С), то у вас должно быть достаточно познаний, чтобы наиболее составить на С програмку, которая читает и строчит простейшие MyISAM таблицы. В зависимости от трудности запросов, которые вы хотите оправдывать с помощью вашей программы, прирост скорости возможно до 5-6 раз. У меня вышло написать программу, которая поделала что-то здоровое, читая полностью таблицу MyISAM, за время, которое сочиняло где-то 1/4 от исполнения такого же наиболее запроса непосредственно в MySQL. На мой взгляд, неплохо. Между прочим, soft вышла только на ~5 Кабэ и ~150 строк кода на Си. Поэтому, если вам внезапно очень требуется супер-высокая продуктивность full scan, то пробуйте MyISAM + собственную програмку на С для чтения из таблицы. Вы станете славно удивлены, в какой мере просто это воплотить, и какой-никакой небольшей кровью у вас есть возможность возвысить производительность чтения в несколько раз. UPD Вы упрашивали числа? Вот вам немного: 1. Числа станут очень сильно в зависимости от осуществлении. Я теснее составил, что у меня получилось убыстрить необходимый ми запрос в 4 раза. Всего, быстрота чтения собрала 1 Гб/сек при габарите записи в двадцать пять байт 2. Различия при FULL SCAN при использовании HANDLER либо SELECT я не обнаружил. FULL SCAN в MyISAM отдает скорость чтения, по моим оценкам, как наименьшее в 3-4 раза более, нежели FULL SCAN в InnoDB. 3. Сам по себе FULL SCAN в MyISAM трудится в 5-10 раз быстрее, чем скан по индексу с подобным же числом записей (при кое-каком хотении, отставание можно сжать до где-то 2-3 раз). 4. В InnoDB скан по PRIMARY KEY работает вдобавок скоро, как FULL SCAN, скан по другому иному индексу работает где-то в 3-4 раза медлительней. Сопоставления с NoSQL не обладают специального резона, если поделается FULL SCAN для огромный таблицы: 1. Memcached не умеет сделать FULL SCAN памяти. 2. HandlerSocket хоть и может FULL SCAN, однако по скорости от SELECT/HANDLER не отличается (если много строчек). Кроме всего прочего, в MySQL 5.1 он не удерживается 3. Mongo, Redis, etc занимают на порядок более памяти/стораджа, что в почти во всех вариантах совершенно недопустимо. Они трудятся быстро, диспуту нет. Но назначение у них отличается. |