数据库的本质、概念及其应用实践(二)

原文请详见:http://www.ucai.cn/blogdetail/7034?mid=1&f=12

可以在线运行查看效果哦!

 

3.3SQLite 数据库

SQLite 数据库也是一个文件数据库,但是不是文本数据库。它是一种自有的二进制格式。最早是由C写的一个库,并且很早也发布PHP的访问扩展,现在一般用的是sqlite3PHP模块名也叫sqlite3

Sqlite 有两个特点:

1、目前已经是非常流行的文件数据库,尤其是嵌入式数据库,在移动应用中也应用得十分普遍。

2、其访问的接口同 MySQL的非常地相似。

具体安装很简单,就是从官网下了代码, make 就可以了,不过代码可真不是一个小个。

3SQLite3 已经是属于关系数据库大家庭的一员,所以它遵循ACID。对于SQL语句的支持也不错,网上也有人写了它和SQL互相导入互出的代码。

也有同MySQL 类似的管理工具,

http://sourceforge.net/projects/sqlitemanager/

 

大家可以搜索SQLite Manager 就能搜索到一堆。

至于具体的操作,不在这里展开,我们五月份的公开课,专门有一讲讲这个。将会比较详细地讲解SQLite 以及应用。

 

3.4MySQL 数据库

 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 * FROM users WHERE name='%s'", mysqli_escape_string($mysqli, $name));
 
echo $query;
/* Select queries return a resultset */
if ($result = mysqli_query($mysqli, $query))
{
    printf("Select returned %d rows.\n", mysqli_num_rows($result));
 
 
    $row = mysqli_fetch_assoc($result);
    print_r($row);
    /* free result set */
 
    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 * FROM users WHERE name='%s'",
    $mysqli->real_escape_string($name));
 
echo $query;
/* Select queries return a resultset */
if ($result = $mysqli->query($query)) {
    printf("Select returned %d rows.\n", $result->num_rows);
 
   
    $row = $result->fetch_assoc();
    print_r($row);
    /* free result set */
   
    $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 = new PDO("mysql:host=$hostname;dbname=samples", $username, $password);
    /*     * * echo a message saying we have connected ** */
    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 模块,一个是php mysql,一个是mysqli,一个是 pdo_mysql 三个模块来分别干同样的事情。如果你单独学习这三个库,会觉得比较枯燥,当你学到一定程度,融会贯通时,特别是对比学习时发现,你学习了其中一个,学习其他的也就并不难了。无非就是如下几步:

1、建立连接,在建立 连接时需要提交用户名,密码,主机,库名,端口等数据。

2、检测连接是否建立成功。

3、组装查询,注意不同的模块,对查询组装时的过滤方法也是不同的。

4、执行查询,获得结果句柄,而不是直接的数据。

5、通过非常相近的函数,从结果句柄中取得数据。

6、把数据放到结果句柄里输出。

7、在离开程序时,需要释放结果集资源。

8、在最后,需要关系开启的数据库连接。

 

3.5MySQL KVDB的一个插件

为什么要用这个插件,并演示这个插件,有几个目的。

一,让大家知道MySQLKVDB,这些软件之间,并没有明显的界限,像KVDB的出现,只是它的处理能力更强,而MySQL由于很多的限制,导致了在简单的场景下,处理能力并不如KVDB强。并不是说不能做。

二、其实有人,将MySQL进行改造,已达到了甚至超过 KVDB的一个高度。就是这个插件所做的,据说做到了 75QPS。并且是生产中可以使用的了,一些发行版均将这个模块包含了进去。

http://yoshinorimatsunobu.blogspot.com/2010/10/using-mysql-as-nosql-story-for.html

 

三、也让大家了解一下MySQL插件的安装。进一步了解MySQL的强大 。

 

https://github.com/DeNA/HandlerSocket-Plugin-for-MySQL

 

wget https://github.com/DeNA/HandlerSocket-Plugin-for-MySQL/archive/master.zip -O HandlerSocket-Plugin-for-MySQL.zip

 

unzip HandlerSocket-Plugin-for-MySQL.zip

 

 进去目录

 

cd HandlerSocket-Plugin-for-MySQL-master/
 
sh autogen.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.73
configure: error: MySQL source version does not match MySQL binary version

 

 

只好查看了一下版本,

 

[root@localhost HandlerSocket-Plugin-for-MySQL-master]# mysqladmin --version
mysqladmin  Ver 8.42 Distrib 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'; 安装插件。

 

 


 
 
插件成功安装。

再在

 

/etc/my.cnf 的 [mysqld] 版块下加入
loose_handlersocket_port    = 9998
loose_handlersocket_port_wr    = 9999
loose_handlersocket_threads    = 4
loose_handlersocket_threads_wr  = 1
loose_handlersocket_address    = [你要监听的IP地址]

 

 

然后重启 mysqld

show processlist




 
 
我们看到,已经成功运行,再netstat看一眼。

 



 
端口监听成功。

 

说明,此插件在MySQL的另一个发行版 Percona Server中已包含。

http://www.mysqlperformanceblog.com/2010/12/14/percona-server-now-both-sql-and-nosql/

 

我们来使用它的 PHP 客户端来测试一下。

 

下载:

https://code.google.com/p/php-handlersocket/downloads/detail?name=php-handlersocket-0.3.1.tar.gz&can=2&q=

 

安装模块。

 

新建测试代码。

新建表格

 

create database hstestdb;
 
CREATE TABLE `hstesttbl` (
  `k` int(11) NOT NULL AUTO_INCREMENT,
  `v` char(255) NOT NULL DEFAULT '',
  PRIMARY KEY (`k`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
 
<?php
$host = '101.251.196.91';
$port = 9998;
$port_wr = 9999;
$dbname = 'hstestdb';
$table = 'hstesttbl';
 
//GET
$hs = new HandlerSocket($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 = new HandlerSocket($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 = new HandlerSocket($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 -c http://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

 

http://101.251.196.91:8983/solr/collection1/select?q=%E6%9C%8D%E5%8A%A1

 

PHP模块下载:

http://pecl.php.net/package/solr

 

 

 

<?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);
 
?>

 

 

 

四、课程总结

       通过上面的这一节课,我们站在一个比较高的高度讨论了数据库的出现和应用场景 。其次,从实用和学术两方面,探讨了一些常用的术语和概念。第三,就是通过实例,分别讲解了不同情况下,对数据库的不同的使用情况。希望这一讲给大家指出一些基本的概念,能让大家对继续参与下面的课程有利。



 

 

猜你喜欢

转载自cyber4cn.iteye.com/blog/2079519