Ich möchte eine Website mit einer sehr kleinen Anzahl von Benutzern erstellen. Die Anzahl der Benutzer liegt zwischen einigen und mehr als einem Dutzend.
Das Backend verwendet PHP und jetzt möchte ich wissen, wie man Daten speichert.
Da die Anzahl der Benutzer sehr gering ist, fühlt sich die Verwendung von MySQL auch sehr niedrig an und kann die Leistung beeinträchtigen, da die Hostkonfiguration zu niedrig ist.
Ich habe darüber nachgedacht, es direkt in einer Datei zu speichern (die Daten haben eine relativ einfache Struktur und JSON kann damit umgehen), aber wenn es eine verwandte Abfrage gibt (z. B. den Join von MySQL), müssen Sie dafür PHP verwenden Die entsprechende Abfrage selbst ist etwas mühsam.
Gibt es einen besseren Weg? Wie eine superleichte Datenbank?
PS: Sie benötigen kein Redis, da die Hostkonfiguration niedrig und der Speicher definitiv knapp ist. Unternehmen wie MySQL und Redis, die hart daran arbeiten, Wunder zu vollbringen, können in einer so schlampigen Umgebung ihre Stärke nicht ausspielen.
Ich möchte eine Website mit einer sehr kleinen Anzahl von Benutzern erstellen. Die Anzahl der Benutzer liegt zwischen einigen und mehr als einem Dutzend.
Das Backend verwendet PHP und jetzt möchte ich wissen, wie man Daten speichert.
Da die Anzahl der Benutzer sehr gering ist, fühlt sich die Verwendung von MySQL auch sehr niedrig an und kann die Leistung beeinträchtigen, da die Hostkonfiguration zu niedrig ist.
Ich habe darüber nachgedacht, es direkt in einer Datei zu speichern (die Daten haben eine relativ einfache Struktur und JSON kann damit umgehen), aber wenn es eine verwandte Abfrage gibt (z. B. den Join von MySQL), müssen Sie dafür PHP verwenden Die entsprechende Abfrage selbst ist etwas mühsam.
Gibt es einen besseren Weg? Wie eine superleichte Datenbank?
PS: Sie benötigen kein Redis, da die Hostkonfiguration niedrig und der Speicher definitiv knapp ist. Unternehmen wie MySQL und Redis, die hart daran arbeiten, Wunder zu vollbringen, können in einer so schlampigen Umgebung ihre Stärke nicht ausspielen.
Verwenden Sie SQLite oder einfach Dateispeicherung. Wenn Dateispeicherung verwendet wird, sollten die Datendateien außerhalb des Webroots platziert werden.
Die richtige Antwort oben ist SQLite. Es ist leichtgewichtig und erfordert keine Dienste, sondern nur Dateien. Der Kunde des Projekts, an dessen Forschung und Entwicklung ich zuvor teilgenommen habe, ist SQLite
Es ist immer noch MySQL. Die Effizienz beim Lesen und Schreiben von Dateien ist geringer als bei der Verwendung von MySQL und wird beim Entwickeln besonders schwierig. Ich schlage vor, dass Sie es zuerst versuchen. Wird die Host-Konfiguration niedriger sein als die des Raspberry Pi? Wenn die Hostkonfiguration bereits niedrig ist, gibt es natürlich keine Möglichkeit, Windows zu installieren.
Wenn Sie mit ORM entwickeln, müssen Sie die Auswahl einer Datenbank in einem frühen Stadium nicht berücksichtigen.
Wenn Sie eine SQL-Entwicklung schreiben, müssen Sie berücksichtigen, dass die Datenbank in der Zukunft geändert wird. Das von Ihnen geschriebene SQL ist möglicherweise nicht kompatibel
SQLite wird mit Erweiterungen geliefert. Obwohl die Funktionen und Datentypen viel einfacher sind als bei MySQL, sind die häufig verwendeten in Ordnung und die Leistung ist ebenfalls sehr gut.
Wenn Sie SQLite verwenden, platzieren Sie die Datendatei am besten nicht im Stammverzeichnis der Website, da die Leute sie sonst herunterladen, wenn sie die URL kennen.
Natürlich können Sie Apache/Nginx so konfigurieren, dass Anfragen abgelehnt werden um auf bestimmte Dateien zuzugreifen, aber es stellt immer noch eine versteckte Gefahr dar,
Deshalb ist es besser, es außerhalb des Stammverzeichnisses der Website zu platzieren.
Außerdem müssen Sie, wenn Sie SQLite verwenden, SQL-Sprache schreiben und verwenden Sie den PDO-Funktionssatz, um Folgendes auszuführen:
<code><?php function db() { static $db; if ($db) { return $db; } else { try { $db = new PDO('sqlite:'.$_SERVER['DOCUMENT_ROOT'].'/../data.db3'); } catch (PDOException $e) { echo $e->getMessage(); exit(); } return $db; } } function insert($title = '', $content = '') { global $app; $db = db(); $stmt = $db->prepare('INSERT INTO posts (post_title, post_content) VALUES (?, ?)'); $stmt->bindParam(1, $title, PDO::PARAM_STR); $stmt->bindParam(2, $content, PDO::PARAM_STR); $stmt->execute(); return ($stmt->rowCount() !== 0) ? array(true, 'lastInsertId' => $db->lastInsertId()) : array(false, 'lastInsertId' => $db->lastInsertId()); } function select($id = '') { global $app; $db = db(); if (!empty($id)) { return $db->query('SELECT * FROM posts WHERE id = '.intval($id))->fetchAll(PDO::FETCH_ASSOC); } else { return $db->query('SELECT * FROM posts')->fetchAll(PDO::FETCH_ASSOC); } } function select_v2($id = '') { global $app; $db = db(); if (!empty($id)) { $stmt = $db->prepare('SELECT * FROM posts WHERE id = ?'); $stmt->bindParam(1, $id, PDO::PARAM_INT); } else { $stmt = $db->prepare('SELECT * FROM posts'); } $stmt->execute(); return $stmt->fetchAll(PDO::FETCH_ASSOC); } function update($id, $title = '', $content = '') { global $app; $db = db(); //echo PDO::ATTR_AUTOCOMMIT; //返回0可见PDO默认禁用自动提交事务. //echo $db->getAttribute(PDO::ATTR_AUTOCOMMIT); exit(); //返回1可见MySQL默认会自动提交事务. //SQLite不支持设置PDO::ATTR_AUTOCOMMIT: //SQLite: Uncaught exception 'PDOException' with message 'The auto-commit mode cannot be changed for this driver' //$db->setAttribute(PDO::ATTR_AUTOCOMMIT, false); $db->beginTransaction(); $stmt = $db->prepare('UPDATE posts SET post_title = ?, post_content = ? WHERE id = ?'); $stmt->execute(array($title,$content,$id)); //所有值视作PDO::PARAM_STR处理 //$stmt->execute(array(':title' => $title,':content' => $content,':id' => $id)); //$stmt->bind_param('ssi', $title, $content, $id); //对比mysqli echo 'sleep(3);'."\n"; sleep(3); $db->commit(); //$db->setAttribute(PDO::ATTR_AUTOCOMMIT, true); //commit提交事务后autocommit记得重新设为true return ($stmt->rowCount() !== 0) ? true : false; } function delete($id) { global $app; $db = db(); return ($db->query('DELETE FROM posts WHERE id = '.intval($id))->rowCount() !== 0) ? true : false; } function delete_v2($id) { global $app; $db = db(); $stmt = $db->prepare('DELETE FROM posts WHERE id = ?'); $stmt->bindParam(1, $id, PDO::PARAM_INT); $stmt->execute(); return ($stmt->rowCount() !== 0) ? true : false; } header('Content-Type: text/plain; charset=utf-8'); $sqlite = "CREATE TABLE IF NOT EXISTS posts ( id INTEGER PRIMARY KEY, post_title VARCHAR(255) NOT NULL, post_content TEXT NOT NULL )"; db()->query('DROP TABLE IF EXISTS posts;') or exit(); db()->query($sqlite) or exit(); //并发时,SQLite在insert时因为库文件被其他请求锁住而导致阻塞 echo "var_export(insert('标题1', '内容1'));\n"; var_export(insert('标题1', '内容1')); echo "\n\n"; echo "var_export(insert('标题2', '内容2'));\n"; var_export(insert('标题2', '内容2')); echo "\n\n"; echo "var_export(select());\n"; var_export(select()); echo "\n\n"; echo "var_export(update(2, '标题2_更新','内容2_更新'));\n"; var_export(update(2, '标题2_更新','内容2_更新')); echo "\n\n"; echo "var_export(select(2));\n"; var_export(select(2)); echo "\n\n"; echo "var_export(delete(2));\n"; var_export(delete(2)); echo "\n\n"; echo "var_export(select());\n"; var_export(select()); echo "\n\n";</code>
Tatsächlich können Sie erwägen, PHP-Arrays direkt in Dateien zu exportieren, um Daten zu speichern.
<code><?php header('Content-Type: text/plain; charset=utf-8'); $file = __DIR__.'/data.php'; //数据文件,别人直接URL访问也下载不了 if(!file_exists($file)) { file_put_contents($file, '<?php return array();'); //file_put_contents($file, ''); } $fp = fopen($file, 'r+'); //读写方式打开,将文件指针指向文件头 if(flock($fp, LOCK_EX)) { //阻塞到获取排它锁 //锁定数据文件后再进行读写 $arr = require $file; //$arr = unserialize(file_get_contents($file)); $arr[] = date('Y-m-d H:i:s'); ftruncate($fp, 0); //清空文件 fwrite($fp, '<?php return '.var_export($arr, true).';'); //fwrite($fp, serialize($arr)); fflush($fp); //在释放锁之前刷新输出 //sleep(10); //睡眠10秒,在此期间其他工作进程的请求将被阻塞 flock($fp, LOCK_UN); //释放锁定 echo file_get_contents($file)."\n"; } fclose($fp);</code>
Es ist erwähnenswert, dass die Leistung von Serialize/Unserialize viel besser ist als die von var_export/require.
Aber var_export/ Der Vorteil von require ist, dass es keine Angst vor dem direkten Zugriff durch andere hat, die Datei im Stammverzeichnis ablegen kann und besser lesbar ist.