Как стать автором
Обновить

SQLite vs MySQL

MySQL *PHP *SQLite *
Ожидает приглашения
Что выгоднее использовать на небольших проектах?
Что выгоднее использовать на небольших проектах?

Предыстория

Ожидая на одном из поддерживаемых сайтов окончания импортирования очередного каталога от поставщиков, задумался, как можно было бы ускорить процесс.

А то ситуация и вправду какая-то нездоровая, да, публичный хостинг с PHP и MySQL, ну так и задачи ведь не космического масштаба, и ожидать по несколько минут, пока сайт переваривает не такой уж и большой поток входной информации, как-то напрягает.

Сама задачка не такая и сложная, идет обработка импорта по API поставщика и далее INSERT-ами и UPDATE-ами все это закачивается уже в БД сайта.

Но этих INSERT-ов и UPDATE-ов довольно много.

И тут я вспомнил, что уже много лет назад копался с SQLite, но в рабочие проекты она не пошла, потому что все говорили: "Фу, производительность никакая, при параллельных запросах все упадет, и тд и тп.", да и с синтаксисом запросов там проблемы были, на тот же MySQL просто перейти было нельзя, надо было бы много чего переписывать, а с учетом того, что все проекты верят, что в будущем они станут как минимум Амазонами с Фейсбуками, то вначале сразу отрубать такую возможность в будущем не хотелось.

Но повзрослев и помудрев(надеюсь), я сейчас выбираю под текущие задачи те инструменты, которые удобнее сейчас, а не в прекрасном возможном будущем.

И вспомнив об этом, я решил затестить, как справится SQLite с волнующей меня проблемой.

И что же, забегая вперед, скажу, что я оказался поражен результатом.

Итак

Я быстро набросал код, который нагружает БД аналогично вышеописанной задачке, соответственно для MySQL и SQLite БД.

Получилось так:

// MySQL

$db = new PDO('mysql:dbname=vashwind;host=localhost;charset=UTF8', 'vashwind', 'очень сложный пароль');

$db->exec("
	SET AUTOCOMMIT = 0;
	DROP TABLE IF EXISTS `foo`;
	CREATE TABLE `foo` (
		`id` int(11) PRIMARY KEY AUTO_INCREMENT,
		`name` varchar(255) DEFAULT NULL
	) ENGINE=InnoDB;
");

$time_start = microtime(true);

$db->beginTransaction();
for($i=1;$i<500000;$i++){
	$db->exec("insert into foo (name) values ('".md5(rand())."') ");
}

for($i=1;$i<500000;$i++){
	$db->exec("update foo set name = '".md5(rand())."' where id=$i");
}
$db->commit();
			
$time_end = microtime(true);
$time = $time_end - $time_start;

echo "Время выполнения mysql: $time секунд <br>";
// sqlite

$db = new PDO('sqlite:db.sqlite'); 

$db->exec("
	DROP TABLE IF EXISTS 'foo';
	CREATE TABLE foo(id INTEGER PRIMARY KEY, name TEXT, text TEXT);
");

$time_start = microtime(true);

$db->beginTransaction();
for($i=1;$i<500000;$i++){
	$db->exec("insert into foo (name) values ('".md5(rand())."') ");
}

for($i=1;$i<500000;$i++){
	$db->exec("update foo set name = '".md5(rand())."' where id=$i");
}
$db->commit();

$time_end = microtime(true);
$time = $time_end - $time_start;

echo "Время выполнения sqlite: $time секунд";

И что же я получаю в итоге?

А вот что:

Время выполнения mysql: 31.970330953598 секунд
Время выполнения sqlite: 4.4192090034485 секунд

То бишь аналогичную задачку SQLite решает в 8 раз быстрее, чем MySQL.

Не поверив своим глазам, подумав, что на конкретном хостинге возможно MySQL плохо настроили, перепроверил результаты еще на двух альтернативных хостингах.

Везде SQLite отработала быстрее от 8 до 15 раз.

Однако..

На текущем проекте с долгим импортом каталогов я SQLite внедрять уже не буду, слишком там много всего уже написано под MySQL, но на будущих проектах присмотрюсь точно.

И да, я полностью отдаю себе отчет, что для высоконагруженных проектов с огромным количеством одновременных пользователей SQLite подходит слабо, но для задач, подобных вышеописанной, она явно достойна рассмотрения.

Теги:
Хабы:
Данная статья не подлежит комментированию, поскольку её автор ещё не является полноправным участником сообщества. Вы сможете связаться с автором только после того, как он получит приглашение от кого-либо из участников сообщества. До этого момента его username будет скрыт псевдонимом.