三、各種數據庫的關系、實踐
3.1、自制簡單文本格式(甚至在PHP中,用數據保存配置)
A、比如有一個AngularJS的示例項目,就用json保存示例數據的格式。
![請輸入圖片描述][1]
B、PHP保存配置數據就更加常見了,TP就是一個典型。
![請輸入圖片描述][2]
3.2、文本數據庫(php text dbapi)
我們從 [http://www.c-worker.ch/txtdbapi/index.php#download][3] 下載了這個比較有名的 文本數據庫引擎。
文本數據的使用場景這些交待一下。
1、比如你的虛擬主機,支持PHP,但是不支持MySQL ,也不支持SQLite的時候就可以發揮用場了。
下載了需要修改一下,
txt-db-api.php 的兩個配置。
$API_HOME_DIR=dirname(__FILE__).DIRECTORY_SEPARATOR;
$DB_DIR=dirname(__FILE__).DIRECTORY_SEPARATOR;
通過[http://samples.app.ucai.cn/20140603/phptxtdb/examples/addressbook.php?lang=de&char=M][3]
就可以看到這個文本數據庫的運行的例子。
然后就可以看到結果保存了。
![請輸入圖片描述][4]
果真是文本不是?
3.3、SQLite 數據庫
SQLite 數據庫也是一個文件數據庫,但是不是文本數據庫。它是一種自有的二進制格式。最早是由C寫的一個庫,并且很早也發布PHP的訪問擴展,現在一般用的是sqlite3,PHP模塊名也叫sqlite3。
Sqlite 有兩個特點:
1、目前已經是非常流行的文件數據庫,尤其是嵌入式數據庫,在移動應用中也應用得十分普遍。
2、其訪問的接口同 MySQL的非常地相似。
具體安裝很簡單,就是從官網下了代碼, make 就可以了,不過代碼可真不是一個小個。
3、SQLite3 已經是屬于關系數據庫大家庭的一員,所以它遵循ACID。對于SQL語句的支持也不錯,網上也有人寫了它和SQL互相導入互出的代碼。
也有同MySQL 類似的管理工具,
[http://sourceforge.net/projects/sqlitemanager/][5]
大家可以搜索SQLite Manager 就能搜索到一堆。
至于具體的操作,不在這里展開,我們五月份的公開課,專門有一講講這個。將會比較詳細地講解SQLite 以及應用。
3.4、MySQL 數據庫
MySQL 從使用上講,大家都比較熟悉了。但是值得注意的是,mysql_query 這樣的方法在php 5.5 時過時。
我們這里做三個簡單的例子。分別用即將廢棄的 mysql 和 mysqli 以 PDO 來操作數據庫。
第一個例子,是過程式地操作MySQL。用的是很普遍的數據庫操作函數,也就是php mysql 擴展的函數。這些函數將在 5.5版中過時,所以我們要抓緊改變了。
<?php/**
* 優才網公開課示例代碼
*
*mysql 過程式操作MySQL的例子
*
*@author 伍星
*@see http://www.ucai.cn
*/ $conn = mysql_connect("127.0.0.1", "samples","ftly5qb");if(!mysql_select_db("samples", $conn))
{ echo mysql_error(); exit;
}
// 這應該由用戶提供,下面是一個示例
$name = 'wxstars';
// 構造查詢
// 這是執行 SQL 最好的方式
// 更多例子參見mysql_real_escape_string()
$query = sprintf("SELECT * FROM users
WHERE name='%s'",
mysql_real_escape_string($name));
// 執行查詢
$result = mysql_query($query);
// 檢查結果
// 下面顯示了實際發送給 MySQL 的查詢,以及出現的錯誤。這對調試很有幫助。
if (!$result) { $message = 'Invalid query: ' . mysql_error() . "\n"; $message .= 'Whole query: ' . $query; die($message);
}
// 結果的使用
// 嘗試 print $result 并不會取出結果資源中的信息
// 所以必須至少使用其中一個 mysql 結果函數
// 參見 mysql_result(),mysql_fetch_array(), mysql_fetch_row() 等。
while ($row = mysql_fetch_assoc($result)){ echo $row['id']."\n"; echo $row['name']."\n"; echo $row['email']."\n";
}
// 釋放關聯結果集的資源
// 在腳本結束的時候會自動進行
mysql_free_result($result);mysql_close($conn);
?>
第二個例子是過程式和面向對象的myqli操作數據庫的例子。
<?php/**
* 優才網公開課示例代碼
*
*mysqli 過程式操作MySQL的例子
*
*@author 伍星
*@see http://www.ucai.cn
*/$mysqli =mysqli_connect("127.0.0.1", "samples", "ftly5qb","samples", 3306);/* check connection */if (!$mysqli)
{
printf("Connect failed: %s\n", mysqli_connect_error()); exit();
}// 這應該由用戶提供,下面是一個示例$name= 'wxstars';// 構造查詢// 這是執行 SQL 最好的方式// 更多例子參見 mysql_real_escape_string()$query = sprintf("SELECT * FROMusers WHERE name='%s'", mysqli_escape_string($mysqli, $name));echo$query;/* Select queries return a resultset */if ($result =mysqli_query($mysqli, $query))
{
printf("Selectreturned %d rows.\n", mysqli_num_rows($result)); $row = mysqli_fetch_assoc($result);
print_r($row); /* free resultset */
mysqli_free_result($result);
}
mysqli_close($mysqli);?><?php/**
* 優才網公開課示例代碼
*
*mysqli 面向對象操作MySQL的例子
*
*@author 伍星
*@see http://www.ucai.cn
*/ $mysqli = new mysqli("127.0.0.1", "samples","ftly5qb", "samples");/* check connection */if($mysqli->connect_errno) {
printf("Connect failed: %s\n",$mysqli->connect_error); exit();
} // 這應該由用戶提供,下面是一個示例$name= 'wxstars';// 構造查詢// 這是執行 SQL 最好的方式// 更多例子參見 mysql_real_escape_string()$query = sprintf("SELECT * FROMusers WHERE name='%s'", $mysqli->real_escape_string($name));echo $query;/* Select queriesreturn a resultset */if ($result = $mysqli->query($query)) {
printf("Select returned %d rows.\n",$result->num_rows); $row =$result->fetch_assoc();
print_r($row); /* free resultset */
$result->close();
}$mysqli->close();?><?php/**
* 優才網公開課示例代碼
*
*PDO 操作MySQL的例子
*
*@author 伍星
*@see http://www.ucai.cn
*/ /* ** mysql hostname ** */$hostname = '127.0.0.1';/* * * mysql username ***/$username = 'samples';/* * * mysql password ** */$password = 'ftly5qb';try{ $dbh = newPDO("mysql:host=$hostname;dbname=samples", $username,$password); /* * * echo a message saying we haveconnected ** */
echo 'Connected to database'."\n"; /* * * The SQL SELECT statement ** */
$sql = "SELECT * FROM users"; foreach ($dbh->query($sql) as $row)
{ print $row['id'] . ' - ' . $row['name'] .' - ' . $row['email'] . "\n";
} /* * * close the database connection ** */
$dbh = null;
} catch (PDOException $e)
{ echo $e->getMessage();
}?>
總結,我們上面使用了三個不同的php 模塊,一個是phpmysql,一個是mysqli,一個是 pdo_mysql 三個模塊來分別干同樣的事情。如果你單獨學習這三個庫,會覺得比較枯燥,當你學到一定程度,融會貫通時,特別是對比學習時發現,你學習了其中一個,學習其他的也就并不難了。無非就是如下幾步:
1、建立連接,在建立 連接時需要提交用戶名,密碼,主機,庫名,端口等數據。
2、檢測連接是否建立成功。
3、組裝查詢,注意不同的模塊,對查詢組裝時的過濾方法也是不同的。
4、執行查詢,獲得結果句柄,而不是直接的數據。
5、通過非常相近的函數,從結果句柄中取得數據。
6、把數據放到結果句柄里輸出。
7、在離開程序時,需要釋放結果集資源。
8、在最后,需要關系開啟的數據庫連接。
3.5、MySQL KVDB的一個插件
為什么要用這個插件,并演示這個插件,有幾個目的。
一、讓大家知道MySQL和KVDB,這些軟件之間,并沒有明顯的界限,像KVDB的出現,只是它的處理能力更強,而MySQL由于很多的限制,導致了在簡單的場景下,處理能力并不如KVDB強。并不是說不能做。
二、其實有人,將MySQL進行改造,已達到了甚至超過 KVDB的一個高度。就是這個插件所做的,據說做到了 75萬QPS。并且是生產中可以使用的了,一些發行版均將這個模塊包含了進去。
http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html
三、也讓大家了解一下MySQL插件的安裝。進一步了解MySQL的強大。
[https://github.com/DeNA/HandlerSocket-Plugin-for-MySQL][6]
wgethttps://github.com/DeNA/HandlerSocket-Plugin-for-MySQL/archive/master.zip -OHandlerSocket-Plugin-for-MySQL.zip
unzip HandlerSocket-Plugin-for-MySQL.zip
進去目錄
cd HandlerSocket-Plugin-for-MySQL-master/shautogen.sh
./configure
發現出錯,要求連同mysql 的源碼目錄一起配置。
下載了一個5.5版的源碼,配置
./configure--with-mysql-source=../MySQL/mysql-5.5.37/
發現出錯。
checking mysql binary... yes: Using/usr/bin/mysql_config, version 5.1.73configure: error: MySQL source versiondoes not match MySQL binary version
只好查看了一下版本,
[root@localhost HandlerSocket-Plugin-for-MySQL-master]#mysqladmin --versionmysqladmin Ver 8.42Distrib 5.1.73, for redhat-linux-gnu on x86_64
發現是5.1.73 的版本
于是乎下了一個5.1.73 的源碼。
成功配置,
./configure--with-mysql-source=../MySQL/mysql-5.1.73/
然后
make
make install
成功安裝。下面再在mysql 中啟用
mysql –uroot –p
執行 install plugin handlersocket soname 'handlersocket.so'; 安裝插件。
![請輸入圖片描述][7]
插件成功安裝。
再在
/etc/my.cnf 的 [mysqld] 版塊下加入
loose_handlersocket_port = 9998loose_handlersocket_port_wr = 9999loose_handlersocket_threads = 4loose_handlersocket_threads_wr = 1loose_handlersocket_address = [你要監聽的IP地址]
然后重啟 mysqld
再show processlist
![請輸入圖片描述][8]
我們看到,已經成功運行,再netstat看一眼。
![請輸入圖片描述][9]
端口監聽成功。
說明,此插件在MySQL的另一個發行版 Percona Server中已包含。
[http://www.mysqlperformanceblog.com/2010/12/14/percona-server-now-both-sql-and-nosql/][10]
我們來使用它的 PHP 客戶端來測試一下。
下載:
[https://code.google.com/p/php-handlersocket/downloads/detail?name=php-handlersocket-0.3.1.tar.gz&can=2&q=][11]
安裝模塊。
新建測試代碼。
新建表格
~~~
create database hstestdb;
CREATE TABLE `hstesttbl` (
`k`int(11) NOT NULL AUTO_INCREMENT,
`v`char(255) NOT NULL DEFAULT '',
PRIMARY KEY (`k`)
) ENGINE=InnoDB DEFAULTCHARSET=utf8<?php$host = '101.251.196.91';$port = 9998;$port_wr =9999;$dbname = 'hstestdb';$table = 'hstesttbl';//GET$hs = newHandlerSocket($host, $port);if (!($hs->openIndex(1, $dbname, $table,HandlerSocket::PRIMARY, 'k,v')))
{ echo $hs->getError(), PHP_EOL; echo "get Error!\n"; die();
}$retval = $hs->executeSingle(1, '=',array('k1'), 1, 0);
var_dump($retval);$retval =$hs->executeMulti( array(array(1,'=', array('k1'), 1, 0), array(1, '=', array('k2'), 1, 0)));
var_dump($retval);unset($hs);//UPDATE$hs =new HandlerSocket($host, $port_wr);if (!($hs->openIndex(2, $dbname, $table,'', 'v')))
{ echo $hs->getError(), PHP_EOL; die();
}if ($hs->executeUpdate(2, '=',array('k1'), array('V1'), 1, 0) === false)
{ echo $hs->getError(), PHP_EOL; die();
}unset($hs);//INSERT$hs = newHandlerSocket($host, $port_wr);if (!($hs->openIndex(3, $dbname, $table, '','k,v')))
{ echo $hs->getError(), PHP_EOL; die();
}if ($hs->executeInsert(3, array('k2','v2')) === false)
{ echo $hs->getError(), PHP_EOL;
}if ($hs->executeInsert(3, array('k3','v3')) === false)
{ echo 'A', $hs->getError(), PHP_EOL;
}if ($hs->executeInsert(3, array('k4','v4')) === false)
{ echo 'B', $hs->getError(), PHP_EOL;
}unset($hs);//DELETE$hs = newHandlerSocket($host, $port_wr);if (!($hs->openIndex(4, $dbname, $table, '','')))
{ echo $hs->getError(), PHP_EOL; die();
}if ($hs->executeDelete(4, '=',array('k2')) === false)
{ echo $hs->getError(), PHP_EOL; die();
}
~~~
3.6、全文檢索
全文檢索是不一個不同于數據檢索的領域。有幾個特點:
A、精確的數據庫查詢,無論是在順序,還是在數據結構上都是非常地確定的。
B、全文檢索一般面向大數據量,所以查詢結果,在順序上和結果上,都不是需要達到 100%精確,當然也有一些技術指標來衡量向著最好的方向前進。
C、精確查詢所查詢的內容,一般是數字型的比較或者是前置匹配等。
D、全文檢索所查的內容,往往是一段文字中的一個或者多個詞。所以只查文本型的數據。
E、精確查詢往往隨著數據量的記錄數到了一定程度,如果是針對文本的查詢,整個速度會下降比較明顯。
F、而全文檢索一般,隨著數據量的增長,下降不能那么明顯。
全文檢索在PHP中有三種實現方式,一是用MySQL 的MyISAM引擎的全文檢索功能。二是使用同MySQL結合緊密的 Sphinx。三是使用較為專業的全文檢索引擎,Lucene。而用Slor來實現量詢。
下載solr
wget -chttp://mirrors.cnnic.cn/apache/lucene/solr/4.8.1/solr-4.8.1.zip
cd solr-4.8.1/example
java –jar start.jar
按教程建立好索引:
[http://lucene.apache.org/solr/4_8_1/tutorial.html][12]
[http://101.251.196.91:8983/solr/collection1/select?q=%E6%9C%8D%E5%8A%A1][13]
PHP模塊下載:
[http://pecl.php.net/package/solr][14]
~~~
<?php
/**
* 優才網公開課示例代碼
*
*Solr 全文檢索客戶端測試
*
*@author 伍星
*@see http://www.ucai.cn
*/ $options = array
( 'hostname' => 'localhost', // 'login' => 'username', // 'password' => 'password', 'port' => '8983',
);$client = new SolrClient($options);$query= new SolrQuery();$query->setQuery('服務器');$query->setStart(0);$query->setRows(50);$query->addField('cat')->addField('features')->addField('id')->addField('timestamp');$query_response= $client->query($query);$response = $query_response->getResponse();
print_r($response);
~~~
?>
四、課程總結
通過上面的這一節課,我們站在一個比較高的高度討論了數據庫的出現和應用場景。其次,從實用和學術兩方面,探討了一些常用的術語和概念。第三,就是通過實例,分別講解了不同情況下,對數據庫的不同的使用情況。希望這一講給大家指出一些基本的概念,能讓大家對繼續參與下面的課程有利。
- PHP技術文章
- PHP中session和cookie的區別
- php設計模式(一):簡介及創建型模式
- php設計模式結構型模式
- Php設計模式(三):行為型模式
- 十款最出色的 PHP 安全開發庫中文詳細介紹
- 12個提問頻率最高的PHP面試題
- PHP 語言需要避免的 10 大誤區
- PHP 死鎖問題分析
- 致PHP路上的“年輕人”
- PHP網站常見安全漏洞,及相應防范措施總結
- 各開源框架使用與設計總結(一)
- 數據庫的本質、概念及其應用實踐(二)
- PHP導出MySQL數據到Excel文件(fputcsv)
- PHP中14種排序算法評測
- 深入理解PHP原理之--echo的實現
- PHP性能分析相關的函數
- PHP 性能分析10則
- 10 位頂級 PHP 大師的開發原則
- 30條爆笑的程序員梗 PHP是最好的語言
- PHP底層的運行機制與原理
- PHP 性能分析與實驗——性能的宏觀分析
- PHP7 性能翻倍關鍵大揭露
- 鳥哥:寫在PHP7發布之際一些話
- PHP與MySQL通訊那點事
- Php session內部執行流程的再次剖析
- 關于 PHP 中的 Class 的幾點個人看法
- PHP Socket 編程過程詳解
- PHP過往及現在及變革
- PHP吉祥物大象的由來
- PHP生成靜態頁面的方法
- 吊炸天的 PHP 7 ,你值得擁有!
- PHP開發中文件操作疑難問答
- MongoDB PHP Driver的連接處理解析
- PHP 雜談《重構-改善既有代碼的設計》之二 對象
- 在php中判斷一個請求是ajax請求還是普通請求的方法
- 使用HAProxy、PHP、Redis和MySQL支撐10億請求每周架構細節
- HTML、HTML5、XHTML、CSS、SQL、JavaScript、PHP、Web Services 是什么?
- 重構-改善既有代碼的設計
- PHP場景中getshell防御思路分享
- 移動互聯時代,你看看除了PHP你還會些什么
- 安卓系統上搭建本地php服務器環境
- PHP中常見的緩存技術!
- PHP里10個鮮為人知但卻非常有用的函數
- 成為一名PHP專家其實并不難
- PHP 命令行?是的,您可以!
- PHP開發提高效率技巧
- PHP八大安全函數解析
- PHP實現四種基本排序算法
- PHP開發中的中文編碼問題
- php.get.post
- php發送get、post請求的6種方法簡明總結
- 中高級PHP開發者應該掌握哪些技術?
- 前端開發
- web前端知識體系大全
- 前端工程與性能優化(下)
- 前端工程與性能優化(上)
- 2016 年技術發展方向
- Web應用檢查清單
- 如何成為一名優秀的web前端工程師
- 前端組件化開發實踐
- 移動端H5頁面高清多屏適配方案
- 2015前端框架何去何從
- 從前端看“百度遷徙”的技術實現(一)
- 從前端看“百度遷徙”的技術實現(二)
- 前端路上的旅行
- 大公司里怎樣開發和部署前端代碼?
- 5個經典的前端面試問題
- 前端工程師新手必讀
- 手機淘寶前端的圖片相關工作流程梳理
- 一個自動化的前端項目實現(附源碼)
- 前端代碼異常日志收集與監控
- 15年雙11手淘前端技術總結 - H5性能最佳實踐
- 深入理解javascript原型和閉包系列
- 一切都是對象
- 函數和對象的關系
- prototype原型
- 隱式原型
- instanceof
- 繼承
- 原型的靈活性
- 簡述【執行上下文】上
- 簡述【執行上下文】下
- this
- 執行上下文棧
- 簡介【作用域】
- 【作用域】和【上下文環境】
- 從【自由變量】到【作用域鏈】
- 閉包
- 完結
- 補充:上下文環境和作用域的關系
- Linux私房菜