Задавайте вопросы, мы ответим
Вы не зашли.
Если все равно одна и та же информация будет занимать одинаковое место?
Почему во всех случаях не делать VARCHAR(255)?
Есть ли хоть какая-нибудь разница? (может быть, сервер будет поплотнее располагать данные на диске, если увидит, что поле короче, и из-за этого ему будет потом легче читать? или что-нибудь подобное вообще...)
Неактивен
Например, индекс будет по-умолчанию того же размера, что и определение VARCHAR().
Неактивен
А что разве индекс в своих ветвях будет короткие строки нулями дописывать?
Неактивен
Эксперимент показал, что нулями дописывать не будет, по крайней мере при хранении на диске в MyISAM. Возможно, при использовании он дописывает нулями в памяти
Неактивен
Возможно, при использовании он дописывает нулями в памяти
А как это можно точно узнать?
(просто хочется как-то раз и навсегда разрешить вопрос о том, стоит ли придумывать длину колонки меньше 255 или нет; указывать всегда 255 удобно, поскольку избавляет от возможных проблем, если длина окажется недостаточной).
Неактивен
А если длина будет больше 255, то все равно не влезет. Индекс никто не запрещает делать только на начало колонки, чтобы не было проблем из-за его излишней длины - это совершенно очевидно, что часть алгоритмов используют индекс как запись фиксированного размера, хотя не посмотрев в исходники точно сказать какие именно не получится.
Неактивен
Да, мне тут тоже мысль пришла, что делать индекс по всему полю VARCHAR, даже если оно меньше 255 символов, - это обычно ни к чему.
Отсюда вывод, что раз индекс всё равно делается не по всему полю, а по левой части, само поле можно смело выставлять в 255 либо в 65535.
Неактивен
Ну, вспомни еще про таблички MEMORY тогда. Они хранят их как CHAR().
Неактивен
Вот про это я забыл
Да, важно.
Кстати. Если MEMORY-таблицу делать как
CREATE TABLE ...
SELECT ... FROM tbl
при этом у tbl есть столбец VARCHAR(255), но самая длинная строка там фактически - например, 100, CHAR-столбец в MEMORY-таблице будет 100 или 255?
Неактивен
Ну, ты бы и сам мог проверить
[aurica] root test > create table a (a varchar(255));
Query OK, 0 rows affected (0.36 sec)
[aurica] root test > insert a values ('blah');
Query OK, 1 row affected (0.00 sec)
[aurica] root test > create table b select * from a;
Query OK, 1 row affected (0.06 sec)
Records: 1 Duplicates: 0 Warnings: 0
[aurica] root test > alter table b engine=memory;
Query OK, 1 row affected (0.07 sec)
Records: 1 Duplicates: 0 Warnings: 0
[aurica] root test > show create table b;
+-------+-----------------------------------------------------------------------------------------+
| Table | Create Table |
+-------+-----------------------------------------------------------------------------------------+
| b | CREATE TABLE `b` (
`a` varchar(255) DEFAULT NULL
) ENGINE=MEMORY DEFAULT CHARSET=utf8 |
+-------+-----------------------------------------------------------------------------------------+
1 row in set (0.00 sec)
[aurica] root test > show table status like 'b'\G
*************************** 1. row ***************************
Name: b
Engine: MEMORY
Version: 10
Row_format: Fixed
Rows: 1
Avg_row_length: 768
Data_length: 129696
Max_data_length: 16690176
Index_length: 0
Data_free: 0
Auto_increment: NULL
Create_time: NULL
Update_time: NULL
Check_time: NULL
Collation: utf8_general_ci
Checksum: NULL
Create_options:
Comment:
1 row in set (0.00 sec)
Неактивен
А как посмотреть show table status для временной таблицы? Вроде бы в этом случае varchar() конвертится в char() максимальной длины, указанной при объявлении varchar().
И ещё хотел убедиться, что в случае использования полей типа TEXT, BLOB для временных таблиц используется не HEAP engine, а MyISAM и данные пишутся на диск.
Неактивен
paulus написал:
Ну, ты бы и сам мог проверить
Самостоятельно не допёр вот до этого:
alter table b engine=memory
А так всё наглядно, спасибо.
Только не понятно, откуда Data_length: 129696 ? Там ведь одна запись длиной в четыре буквы.
И Avg_row_length тоже должно быть не 768, а 256*2*4 - 2048.
Неактивен
Так UTF8, три байта, 256*3 = 768
А память выделяется страничками, тут уж никуда не денешься.
Неактивен
Так UTF8, три байта, 256*3 = 768
Да, забыл, что английские буквы. Если три байта - ты, наверное, вставлял 'bla', а не 'blah' (а то бы было четыре).
память выделяется страничками
[раз уж затронули эту тему] Всегда хотел узнать, что есть такое страничка и зачем вообще хранить данные по страничкам?
Неактивен
Я вставлял именно blah. Мог бы вставить blahminor, размер бы не поменялся. Вопрос
на понимание: почему? Кажется, ты путаешь некоторые размеры
Страничка — это некоторый блок памяти, работа с которым идет атомарным образом.
Просто удобный способ работы с данными. Допустим, у тебя есть твой шаблонизатор.
Для того, чтобы распарсить какой-то блок, ты берешь всю структуру загруженных
шаблонов и работаешь с ней. Если бы твое приложение было многопоточным (например,
держало все шаблоны в памяти), то тебе приходилось бы ставить mutex на обращении
к дереву. Потом бы ты обнаружил, что блокировка всего дерева неэффективна, т.к.
это эффективно сводит многопоточное приложение к однопоточной работе. Ты решишь
брать mutex на куски деревьев. Потом этого мало и ты решишь, что надо блокировать
куски кусков — странички
Неактивен
Кажется, ты путаешь некоторые размеры
Видимо, да :0
Поясни, пожалуйста.
Про страницы: т.е в рамках одной страницы получается все-таки однопоточность?
Неактивен
1. Кодировка utf8: 1-3 байта на символ.
2. VARCHAR(255): 0-255 символов для хранения информации + 1 символ для
хранения живой длины строки
3. Переделываем в MEMORY и 2 пункт эффективно выделяет полную память
в 256 * 3 байт. Вне зависимости от того, что там хранится.
--
Ну, так есть, например, в BDB. В InnoDB пошли еще дальше и ставят
блокировки на строки (а страничка стала некоторым атомарным куском в
таблице; например, если ты меняешь данные на страничке одной транзакцией
при том, что другие транзакции находятся в уровне изоляции выше, чем
READ UNCOMMITTED и читали эту страничку, страничка дублируется и
изменения применяются к дублю), но оперируются данные все равно
постранично, т.к. это удобно.
Неактивен
Да, я че-то забыл, что на один символ нужно 1-3 байта,а не 256*1-3 (бывают иногда такие помутнения)
В общем, ясно, спасибо.
Неактивен