Могу ли я «оптимизировать» запрос, включающий текстовый столбец?

#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 — Я добавил к своему ответу. Если вам нужны более подробные сведения, начните новый вопрос и сузьте его до того, о каком движке вы хотите поговорить.