Очень странная ситуация.
Я решил "поиграть" с базой данных и создал БД с 20 000 000 записей и провёл пару тестов. По идеи, запись с индексом должна быть дольше, а поиск элементов быстрее. Тесты были такие:
Вопросы тестирования
заполнение БД;
добавление 100 элементов;
получение 100 000 элемента;
получение 20 000 000 элемента;
получение элементов в котором встречается число 2555;
Сейчас я приведу пример своего кода на nest js, но он лишь обёртка, так что под ним я ещё и запишу команды ( SQL-запросы). Так же я в обоих случаях заполнял БД одинаково без nestjs ( смотрите в SQL-запросах). Тесты в обоих случаях одинаковые, сравниваю по индексу key ( само поле chatKey ).
Вот код на nestjs:
spoiler
модель
@Table({tableName: 'chats', createdAt: false, updatedAt: false})
export class MessageTable extends Model {
@Column({type: DataType.INTEGER, primaryKey: true, unique: true, autoIncrement: true})
id: number;
@Column({type: DataType.JSON})
members: number[];
@Index('key')
@Column({type: DataType.TEXT})
chatKey: string;
@Column({type: DataType.INTEGER})
author: number;
@Column({type: DataType.STRING(32)})
date: string;
@Column({type: DataType.STRING(255)})
data: string;
@Column({type: DataType.STRING(511)})
files: string;
}
тесты
addMessage = (number: number) => {
return new Promise( (res) => {
this.ChatRepository.create({
id: 20000000 + number,
author: number,
date: 'asd',
chatKey: (20000000 + number).toString(),
data: 'das',
files: '[]',
members: [1]
}).then( () => {return res('das')});
})
}
getMessageByKey = (number) => {
return new Promise( (res) => {
this.ChatRepository.findAll({where: {chatKey: number.toString()} } )
.then( (response) => res(response))
})
}
getMessagesByKey = (number) => {
return new Promise( (res) => {
this.ChatRepository.findAll({where: {
chatKey: {
[Op.like]: `%${number.toString()}%`
}
} } )
.then( (response) => res(response))
})
}
for (let indexx = 0; indexx < 100; indexx++) {
this.messageService.addMessage(indexx + 3)
.then( () => {if (indexx === 99) {
console.log('Ready by ' + (Date.now() - this.DateNow) );
} })
}
this.messageService.getMessageByKey(100000).then( (res) => {
console.log(res);
console.log('Ready by ' + (Date.now() - this.DateNow));
})
this.messageService.getMessageByKey(20000000).then( (res) => {
console.log(res);
console.log('Ready by ' + (Date.now() - this.DateNow));
})
this.messageService.getMessagesByKey(2555).then( () => {
console.log('Ready by ' + (Date.now() - this.DateNow));
})
SQL-запросы
INSERT INTO chats(author, "chatKey", "data", date, files, id, members)
SELECT 1, s.id '"asd"', '"asdasd"', '"[asdfasdf]"', s.id, '[12, 13]'
FROM generate_series(1, 20000000) as s(ID)
ORDER BY random()
Executing (default): INSERT INTO "chats" ("id","members","chatKey","author","date","data","files") VALUES ($1,$2,$3,$4,$5,$6,$7) RETURNING "id","members","chatKey","author","date","data","files";
Executing (default): SELECT "id", "members", "chatKey", "author", "date", "data", "files" FROM "chats" AS "MessageTable" WHERE "MessageTable"."chatKey" = '100000';
Executing (default): SELECT "id", "members", "chatKey", "author", "date", "data", "files" FROM "chats" AS "MessageTable" WHERE "MessageTable"."chatKey" = '20000000';
Executing (default): SELECT "id", "members", "chatKey", "author", "date", "data", "files" FROM "chats" AS "MessageTable" WHERE "MessageTable"."chatKey" LIKE '%2555%';
А теперь самое интересное. Я тестил в два дня, так как создание с индексами заняло больше времени, чем я думал, поэтому я в первом случае проводил 5 тестов и усреднял значения, в в тесте с индексами писал разброс.
creating without index - 11 min 18 sec
adds 100 elements without index - 7803
get 100 000 element without index - 942
get 20 000 000 element without index - 5478
get all element where key === 2555 without index - 1195 - 6141
creating - 2 hr 16 min.
adds 100 elements - 5206 - 58907
get 100 000 element - 3813 - 56000
get 20 000 000 element - 1922 - 7316
get all element where key === 2555 - 2847 - 32458
Почему-то в среднем поиск без индекса быстрее, чем с ним. У меня два вопроса. Первый, что я сделал не так? Второй, стоит ли в этом случае использовать индексы?