#mysql #query-optimization
#mysql #запрос-оптимизация
Вопрос:
Если у меня есть эта таблица строк 400M:
create table my_table
( id int,
filled tinyint,
content text not null
) engine=myisam
могу ли я предотвратить дополнительный доступ к содержимому (из-за типа столбца text) с помощью:
select id,if(filled,content,'') from my_table
(заполнено 0 или 1)?
Или, если содержимое может быть нулевым, будет
select id,ifnull(content,'') from my_table
может быть лучше (все еще с точки зрения производительности, поскольку тогда возникнут нулевые накладные расходы)?
Комментарии:
1. Начнем с того, что два запроса не выполняют одно и то же. Что вы пытаетесь сделать?
2. Я хочу предотвратить дополнительный доступ к содержимому (из-за текста типа столбца), если он не заполнен
3. «дополнительный доступ к контенту» — в первом запросе вы выбираете все. «Есть ли другой, лучше, чем эти?» — учитывая, что вы их не индексировали — каждый запрос будет включать полное сканирование.
4. Правильно. и при сканировании таблицы я не хочу, чтобы содержимое вызывало дополнительный доступ к диску, когда он не заполнен
5. уместно: dba.stackexchange.com/q/103370/37113
Ответ №1:
Ваш вопрос неточен. Может ли строка иметь filled = 1
и content = 'some text'
?
Если да, то IF(filled, content, '')
это имеет смысл.
Если нет, то избавьтесь от filled
и просто установите content
значение ''
. Стоимость доступа к пустой строке для content
является крошечной.
Насколько велик content
обычно? Если обычно это всего лишь сотни символов, разница в производительности невелика.
Не используйте MyISAM, переключитесь на InnoDB.
У вас много DELETEs
или UPDATEs
? Если да, то .MYD-файл MyISAM может быть фрагментирован. Это означает, что content
они могут быть разбросаны по всему диску. Если у вас нет обновлений или удалений, то content
это «прямо там», следовательно, практически бесплатный доступ.
Напротив, InnoDB иногда ставит TEXT
и BLOB
«вне записи».
Но что лучше или хуже? Отсутствие записи (в некоторых ситуациях) по сравнению с фрагментацией (в некоторых ситуациях).
Вы извлекаете только одну строку? Или много таких строк? Это еще одна область, где MyISAM и InnoDB реализованы совершенно по-разному. MyISAM необходимо перейти content
к «следующей» строке. (Я не буду вдаваться в пространное обсуждение того, где, вероятно, будет находиться «следующая» строка.)
Итог: не беспокойтесь об оптимизации, но измените на InnoDB (по многим причинам).
Где, вероятно, будет «следующая» строка?
MyISAM… Строки добавляются в .MYD в порядке вставок. Но после обновлений или удалений новые / измененные строки, как правило, сначала заполняют пробелы, оставляя добавление в файл в качестве последнего средства.
InnoDB… Строки находятся в дереве B , упорядоченном по PRIMARY KEY
. BTree заблокирован блоками размером 16 КБ. У вас есть TEXT
столбец, поэтому он становится более сложным…
Для «маленьких» ТЕКСТОВЫХ столбцов несколько строк будут помещаться в 16 КБ. Если, скажем, content
строки размером 1 КБ, в блок будет помещено до 15 строк. Если они намного больше, то content
будут сохранены «вне записи».
Строки в блоке по существу все равноудалены друг от друга. (Большие усилия связаны с загрузкой блока в кэш и поиском блока.)
Блок «следующий» (или «предыдущий») находится всего в нескольких шагах от доступа к диску — см. » » в «B Tree».
Когда блок переполняется, он «разбивается» на два блока, в каждый из которых входит несколько строк. Новый блок выделяется где-то, редко рядом.
С твердотельными накопителями все блоки «равноудалены» друг от друга. С HDD задержки вращения и движение руки усложняют выбор времени, какой блок может быть «ближе», чем какой-либо другой блок.
Комментарии:
1. Принято. Кстати, где я могу прочитать некоторую информацию о том, где , вероятно, будет «следующая» строка?
2. @guigoz — Я добавил к своему ответу. Если вам нужны более подробные сведения, начните новый вопрос и сузьте его до того, о каком движке вы хотите поговорить.