Задавайте вопросы, мы ответим
Вы не зашли.
Есть Таблица. Данные в неё планируеться добавлять интенсивно ( до 100 инсертов в секунду). Выборка из таблицы ещё интенсивнее.
Вопрос №1:
CREATE TABLE table1 (
id INT(10) NOT NULL AUTO_INCREMENT,
rid INT(10) NOT NULL,
text_field CHAR(512) NOT NULL,
PRIMARY KEY (id,rid)
);
// хотя уникальность ключа гарантируеться даже одним толко id;
Запрос к таблице : SELECT * FROM table1 where (id > 1 and rid = 1);
EXPLAIN отвечает : Possible keys : Primary, Key : NULL ;
Если я запрос поменяют ну наеример на SELECT * FROM table1 where (id = 1 and rid = 1); то при этом EXPLAIN скажет что ключ использовался (что ожидаемо).
Потом сделал почти такую же таблицу :
CREATE TABLE table2 (
id INT(10) NOT NULL AUTO_INCREMENT,
rid INT(10) NOT NULL,
text_field CHAR(512) NOT NULL,
PRIMARY KEY (id)
);
Запрос : SELECT * FROM table2 where (id > 1 and rid = 1);
EXPLAIN так же мне сказала что ключ не исползовался (как и в любом варианте , если не ставить знак равенства в where выражении касающегося PK).
Теперь суть вопроса :
На практике какой варинт работает быстрее на SELECT ? И в каком из вариантов вставка сложнее (интуитивно кажеться что в первый сложней (там PK "сложней")). То есть меня интересует что если эти варианты работают на поиске одинаково - то выбрать тот у кототого быстрее вставка(вероятно вариант 2). Может стоит эту таблицу хранить в оперативно памяти ? Вобще буду рад услышать советы.
Неактивен
100 инсертов в секунду - это очень много. Вам безусловно стоит подумать о
кластеризации Вашего сервиса. Если, конечно, данных много.
Таблицу, разумеется, стоит держать в памяти (если Вы можете себе это позволить).
Ключ не используется, потому что поиск по всей таблице работает быстрее.
При такой cardinality индекса Вам имеет смысл вообще не делать индекс, т.к.
он не используется (кроме случая InnoDB).
P.S.
(100 инсертов в секунду) x (520 байт на строку) = 52000 байт в секунду = 187М в час.
Неактивен
Уточняю. (вы наверное вдоволь посмеялись прос 187 метров/час). Запииси будут быстро становиться лишними. и будут довольно быстро удаляться. То есть смысл будут иметь последние 1000 записей, например. Остальные удалять. Просто меня что сбивало с толку. id - мой первичный ключ хотя бы по той причине что на нём должен быть инкримент( если id не PK то автоматический инкримент создать я немогу.). В общем меня смущает ну например то что id больше заданного значения оно найдёт бысто( это же пк) но потом ему нада будет сделать n сравнений с записями от заданного id до максимально существующего. То есть n может быть 10 или 100 или 300. На некладно ли это ?. Вобще существует ли возможность это как то оптимизировать или это иденственное что вобще можно сделать .
P.S. : что бы не было всяких домыслов и удивлений , я всего навсего пишу веб-чат.
Неактивен
Ну и напоследок :
Вобще (изначательно задумывалось одну большую таблицу с сообщениями разбить на несколько более мелких . Таблица у меня останеться почти такая же а запрос будет иметь вид : SELECT * FROM table1 where (id > число); Насколько быстро будет просходить нахожедние всех строк с ключом больше заданного уже без дополнительных сравнений или чего то ещё ?.
//
Вопрос из области любопыства : при ришении задачи как я пытаюсь решить (веб-чат) , при нагрузке ну допусти 100-300 пользователей онлайн - могут ли себя оправдать файлы ?
Неактивен
Думаю, что запрос он выполняет так - сначала проверяет rid=1, а затем id>1. Попробуйте создать ключ в другом порядке KEY(rid,id), посмотрите будет ли использоваться. И посмотрите SHOW INDEX FROM table1\G
Подумайте над использованием ENGINE=MEMORY, в таком случае все будет храниться в памяти (но при перезагрузки сервера сохраняться не будет). Вы можете вести архив дополнительно в таблице MyISAM, а SELECT делать из MEMORY таблицы
Неактивен
300 пользователей онлайн не могут генерить 100 инсертов в секунду...
Не уверен, что есть смысл использовать индекс вообще на таблице в 1000
записей в памяти. Обращение по индексу будет в любом случае медленнее
полного поска по таблице кроме случая вытаскивания 1-2 строк по ключу.
В случае вебчата Вы никогда не будете вытаскивать строки по ключу.
Если захотите делать ключик, учтите, что по-умолчанию в MEMORY-таблицах
ключ создается HASH, а не BTREE, что не позволит Вам делать сравнение
с использованием ключа. Для создания ключика BTREE надо это указать явно.
Неактивен
paulus написал:
300 пользователей онлайн не могут генерить 100 инсертов в секунду...
Не уверен, что есть смысл использовать индекс вообще на таблице в 1000
записей в памяти. Обращение по индексу будет в любом случае медленнее
полного поска по таблице кроме случая вытаскивания 1-2 строк по ключу.
В случае вебчата Вы никогда не будете вытаскивать строки по ключу.
Если захотите делать ключик, учтите, что по-умолчанию в MEMORY-таблицах
ключ создается HASH, а не BTREE, что не позволит Вам делать сравнение
с использованием ключа. Для создания ключика BTREE надо это указать явно.
Спасибо. Всё учту. Хочу обьяснить своё сметение и желательно развейте его.
Запрос SELECT * FROM table1 where (rid = число_какоето_ни_суть_какое); к таблице без первичного ключа (таблица в памяти) будет быстрее запроса
SELECT * FROM table1 where(id > число and rid = число_какоето_ни_суть_какое) к таблице у которой будет первичный ключ с инкриментом ?
Неактивен
Приведите пожалуйста конкретные цифры по скорости работы запросов. Абстрактно на основании EXPLAIN сказать о скорости можно не во всех случаях. Попробуйте также создать ключ в обратном порядке - возможно такой ключ будет использоваться.
Неактивен
Все зависит от распределения значения ключа по таблице.
Пусть, например, у Вас есть таблица на 1000 записей, в которой
есть ключ на поле А, при этом каждая строчка в таблице уникальна.
Тогда выборка с WHERE A=VALUE будет использовать ключ наиболее
эффективно - достанет 1 строчку по ключу.
Рассмотрим противоположный пример: у Вас в таблице 500 записей
со значением 1, а 500 записей со значением 2. Тогда выборка WHERE
A=2 будет работать быстрее без использования индекса, т.к. это
приведет к меньшему количеству перемещений по диску (последовательное
чтение всегда быстрее).
Именно поэтому индекс не работает на поиске id>1.
Неактивен
Спасибо.В общем стало ясней.
Неактивен
question написал:
Вопрос из области любопыства : при ришении задачи как я пытаюсь решить (веб-чат) , при нагрузке ну допусти 100-300 пользователей онлайн - могут ли себя оправдать файлы ?
Можете использовать MEMORY таблицу - 300-500 человек в чате mysql свободно выдерживает. При большем количестве пользователей, разумно использовать в качестве хранилища сообщений memcached. При количестве пользователей >1000 уже начнет "загибаться" Apache (оверхед на переключения контента задач) и надо писать чат как http демон с неблокируемой обработкой сети (сискол poll/select/etc).
Неактивен
По поводу загибания апача есть очень классный опыт: апач жрет немеряно процессора,
поэтому, если ему поставить nice побольше, overall комбинации апач+mysql окажется куда
выше.
Неактивен