一 : 数据时空(1)
“警报警报,有敌人入侵,五分钟后将自爆!”警报器响了。
“怎么办!怎么办!这可是我一生的心血啊!不能就这么毁了啊!哪个该死的王八蛋啊!哎呦!”一个白发苍苍的老博士感叹道。“你说什么啊,爸爸,还不赶快逃啊!”旁边的一位年轻人说着。博士说:“唉,这都是我这许多年收集来的数据,一共有四份,每一份都密关重要的啊。“啊,这样啊。哦,对啊!爸,你记不记得上次我和你无聊时造了个功能,他正是把数据转化成人体啊!”年轻人说。
这时,博士哦了一声,“对啊!”
接着,博士在大型电脑旁按了那些五颜六色的按钮。“转化中,请稍后---”电脑“说”了一句。这段时间中,年轻人和博士都在抓耳挠腮的等待着转化。
“叮--”电脑响了。忽然,一旁的大型玻璃桶中出现了几个在啼哭的婴儿,然后博士连忙从中把他们抱到了桌子上,用布包着他们。博士又说:“快,把他们背出去。”
“嗯,可是您呢?”年轻人说。“警报,离爆炸还剩一分钟”警报器又响了起来。
“快啊!,来不及了!我不用你管!”博士焦急的说。“不!就算死我也要跟您死在一块!求您了,老爸”年轻人说。
博士说:“唉~好吧,我们就坐在那边的椅子上对抗敌人吧,你把孩子们背上。”之后,两人坐上后,博士迅速的按了年轻人坐在那张凳子上的按钮,然后年轻人的椅子就飞出了实验室,“爸!为什么!为什么啊——!”年轻人喊。
“爸爸永远爱你!你要把他们抚养成人啊!”博士大喊。
“5、4、3、2、1——”(警报器响),“砰!!!”,
六年级:511228262
二 : 数据库:django ORM如何处理N+1查询
数据库N+1查询是个常见的问题,简单描述场景如下
class Category(models.Model):
name = models.CharField(max_length=30)
class Article(models.Model):
title = models.CharField(max_length=30)
body = models.TextField()
category = models.ForeignKey(Category)
time = models.DateTimeField()
#----列表页模板{% for a in Article.objects.all %}
{{ a.title }}
{{ a.category.name }}
{% endfor %}
在生成列表页面时,首先执行一次
select * from article limited 0,N
然后逐条获取category.name,又需要执行N次
select name from category where id = category_id
所以N+1问题其实应该叫做1+N 问题,这只是一个数据库设计模式的问题.但是会对数据库带来很大的压力,一个简单的列表页可能会有几百次数据库查询
N+1问题并不是ORM独有,只是使用orm的时候,数据库表中的行变成一个对象,于是很自然的就容易使用上面的方法来进行查询不使用orm进行编程的情况,一般直接用子查询或者inner join
select a.*,c.name from article a,category b where a.category_id = b.id
子查询或者inner join对数据库来说,也是很费资源的操作,因为需要锁表,高并发的情况下很容易锁死
要解决1+N问题一般有3种方法
数据库反范式设计,说直白点,就是把表合并,设计成冗余表,这可能会带来两个问题
所以,这种方案显然存储效率不高,但是如果针对这两种情况进行优化,也算是是一种不错的解决办法, MongoDB就是这样干的
加缓存 把整个列表页加上缓存. 这样 无论是继续执行1+N次查询,还是用inner join 1次查询搞定,都可以.
这种方法的缺点是
把N+1次查询变成2次查询
简单说 先执行 select *,category_id from article limited 0,N
然后遍历结果列表,取出所有的category_id,去掉重复项
再执行一次 select name from category where id in (category id list)
把子查询/join查询 分成两次,是 高并发网站数据库调优中非常有效的常见做法,虽然会花费更多的cpu时间,但是避免了系统的死锁,提高了并发响应能力
数据库本身处理不了高并发,因为我们只能保证单个数据项的操作是原子的,而数据库的查询是以 列表为基本单元,这是个天然矛盾,无解
数据库设计范式不在web framework能力范围内,所以django的ORM 只支持后面两种做法
Article.ojbects.select_related()
这就是inner joinArticle.objects.prefetch_related('category')
这是2次查询本文地址: 鲁塔弗原创文章,欢迎转载,请附带原文链接
三 : 重级参与者“乱入”数据库迎黄金时代
【IT168 评论】就在前几日, 浪潮在北京正式发布K-DB数据库。早在今年8月份,就看到K-DB技术开放日招募技术爱好者的帖子,于是笔者也默默的关注着这个数据库。其实早在浪潮发布会之前,论坛里网友们已开始讨论“K-DB”:用“乱入”这个动漫词语来形容K-DB,相信大家早有体会,这个做服务器的厂商怎么去做数据库了。
关于浪潮发布K-DB你怎么看?你会去试用这个新品吗?笔者整理了一些网友观点,欢迎大家到论坛中交流吧!【】
关于K-DB的发布 DBA怎么看?
网友lispo说“确实比较期待国内大佬的核心软件。”“要完全重新基于数据库的基本原理来实现一个全新的数据库, 感觉不太可能, 如果是全新的, 那么会更有兴趣一些如果是基于开源的数据库二次开发的话, 相对来说兴趣少很多, 虽然改起来也是非常要技术的活, 但是多多少少会有点索然无味的感觉吧!”网友wangwenan6这样说。小部分网友对于K-DB的发布采取围观其变的态度。
也有不少网友的支持和鼓励——网友nail78“国产数据库任重而道远。”网友tanjianping的辣评:“就算K-DB再牛,一个产品要打入整个市场也是需要一段时间的,再者ORACLE占据整个半壁江山,是说替代就能替代的?现在K-DB到最后是什么样谁也不知道。但毕竟是国产的,还是支持!”
网友xuexiaogang:从发布来说我觉得做得不错。能做到这个样子已经很好了。国产数据库真的不容易。至于其他的在安全性、高可用以及其他等等技术领域的成就,我们就只能拭目以待了。全世界200多种数据库,可以说百花齐放,百家争鸣。希望多出一些好的数据库,吸取别人的优点。举例来说oracle update tab set a=b;oracle会更新全表,而mysql则不会更新已经是a=b的行。我希望国产数据库能把各种好的地方吸取一下。
【来自官方的介绍】K-DB是一款专为天梭K1定制优化的数据库,由浪潮和韩国第一大企业级软件提供商Tmax公司共同研发。此前,IBM的DB2,SAP的Sybase都已经相继推出了专门支持天梭K1的数据库版本。浪潮与这些伙伴为众多的企业级用户搭建了关键业务系统。但是浪潮的很多客户是Oracel的数据库用户,对异构数据库平台迁移有着现实的需求,他们需要一款体系结构类似、迁移简单、可靠、高性能的数据库产品,因此推出K-DB。“建立K生态”浪潮集团副总裁彭震这样表示。
研发要靠硬技术 网友这样评论K-DB
许多传统客户在应用数据库中的最大问题就是迁移的不确定性,笔者了解到浪潮为K-DB开发了完善的工具包,从Oracle到K-DB的迁移工作,包括数据结构的比对、SQL语句检查等,均可由工具软件自动完成,不仅降低迁移的技术复杂度和工作量,也使得迁移风险可控。
据说“酷似”Oracle,网友hai503表示如果可以,想要试用下。大家对于体验新品是怎样的情绪?网友wangwenan6表示:“会看文档是否完备,没有完备的文档,估计只是有兴趣看看官方的说明和介绍,测试环境试着搭起来, 有空的时候上手体验体验还是不错的!”
“一键迁移的好处,如果纯手工进行迁移操作的时候,DBA很难找到迁移过程中出现的问题。我们的一键迁移工具会提供一个功能,迁移完了以后可以帮你校验,如果真的发现系统有错误会通过程序帮你筛选出来,可以把呈现的问题给到DBA他可以手工去做,加大了客户在迁移过程中的信心”,浪潮集团主机事业部副总经理江豫京表示。
数据库市场的发展对未来市场竞争的影响
伴随着中国十几年的信息化进程,中国的IT应用市场催生了一个巨大的蛋糕。然而,由于技术的垄断,这个巨大的IT应用蛋糕一直被独享。数据库作为基础软件的关键环节,承载着对信息安全最重要的数据。然而这一环节却是国产基础软件中发展最薄弱的环节。
网友daizyflower说:开放式的数据库将是未来的方向!
网友xuexiaogang说道:后IOE时代是让更多的场景选择合适自己的数据库,而不是一家独大,也不是人云亦云的跟风大数据。没有几个公司有大数据的基础和环境的,决策者理智一些用好自己现有的数据库,选择合适自己的数据库。数据库是一片大好,但是不要把他用烂了,污染了。盲从大数据会导致不合适自己系统的数据库发挥出较低的水平,而败坏了名声。
总的来说,K-DB的诞生就是为了替代在关键业务领域Oracle不支持K1的选择,从而完善了浪潮K1解决方案。曾经Power + Oracle被誉为是OLTP的黄金组合,如今K1+K-DB的组合则让用户多了一种选择。
最后引用网友xkf01的话“我们期待浪潮的发展吧!“
四 : 从Web查询数据库之PHP与MySQL篇
PHP+MySQL的组合是构建网站的一个常见搭配,不过如何使用PHP通过Web访问MySQL数据库呢?下面从Web数据库架构的工作原理讲起。
从Web查询数据库:Web数据库架构的工作原理
1、一个用户的浏览器发出一个HTTP请求,请求特定的Web页面,在该页面中出发form表单提交到php脚本文件(如:results.php)中处理;
2、Web服务器接收到对results.php页面的请求后,检索文件,并将其传递给PHP引擎处理;
3、PHP引擎开始解析脚本。脚本主要包括了连接数据库和执行查询的命令。PHP启动了对MySQL服务器的连接并向该服务器发送适当的查询;
4、MySQL服务器接收到数据库查询的请求,开始处理这个查询,并将查询结果返回给PHP引擎;
5、PHP引擎完成了脚本的运行后,将该HTML返回Web服务器;
6、Web服务器再将HTML返回给客户端浏览器,用户就可以看到响应后的结果页面;
从Web查询数据库的基本步骤
1、检查并过滤来自用户的数据 首先,我们将过滤用户可能在其搜索条件的起始或结束位置不小心输入的空白字符,这是用函数trim()来实现。 我们这么麻烦的检查用户输入数据的原因是防止多个接口连接数据库,因为用户从不同的界面进入,这样可能导致安全问题。 然后,当准备使用用户输入的任何数据时,也要适当的过滤一些控制字符,当用户输入数据到数据库时必须转义数据,,此时 使用盗的函数有addslashes()函数、stripslashes()函数和get_magic_qutoes_gpc()函数。addslashes()函数为了数据 库查询语句等的需要在某些字符前加上了反斜线;stripslashes()函数去掉字符串中的反斜线字符;get_magic_qutoes_gpc()函数 魔术添加转义字符 “”,获取当前活动配置magic_quotes_runtime设置,如果运行时关闭魔术引号,返回0,否则返回1。我们也可以使用 htmispecialchars()对HTML中的特殊意义字符警醒编码,htmispecialchars()函数把一些预定义的字符转换为 HTML 实体 【预定义的字符是:& (和号) 成为 & " (双引号) 成为 " ' (单引号) 成为 ' < (小于) 成为 < > (大于) 成为 >】
2、建立一个到适当数据库的连接 PHP为连接MySQL提供了函数库mysqli(i表示改进)。 当在PHP中使用mysqli函数库是可以使用面向对象或面向过程的语法:
A、面向对象, @ $db = new mysqli('hostname','username','password','dbname');返回一个对象
B、面向过程: @ $db = mysqli_connect('hostname','username','password','dbname');返回一个资源,这个资源表示数据库的连接,而且 如果使用过程方法,必须将这个资源传递到mysqli的所有其它函数。这与处理函数非常类似。
mysqli的大多数函数都有面向对象接口和过程接口,二者的差异则在于过程版本的函数名称以mysqli_开头,同时要求传入mysqli_connect()函数获得的资源句柄。 对于这个规则来说,数据可连接是一个异常,因为它是由mysqli对象的构造函数来创建的。因此尝试连接时需要进行检查,mysqli_connect_errno()函数将在出现连接 错误时返回一个错误号,如果成功,则返回0。
请注意:
当连接到数据库是,通常会议错误抑制符@作为第一含代码。这样可以巧妙的处理任何错误,也可以通过异常来处理。另外,MySQK对同时连接 数据库的连接数量有一定的限制。MySQLi参数max_connections决定了同时连接的个数,该参数和相关的Apache参数MaxClients的作用是告诉服务器拒绝新的连接请求, 从而保证系统资源不会再系统忙碌时或系统瘫痪时被请求或使用。要设置Apache中的MaxClients参数可以编辑系统中的httpd.conf文件。要为MySQLi设置max_connections参数 可以编辑文件my.conf。 选择使用的数据库: 在MySQL命令行使用 use dbname;命令;在php中可以用$db->select_db(dbname);或mysqli_select_db(db_resource,dbname)。
3、查询数据库 要执行数据库查询,首先应构造查询语句:$query = "select * from user";然后运行 $result = $db->query($query);或者$result = mysqli_query($db,$query); 面向对象版本将返回一个结果对象;过程版本将返回一个结果资源。无论何种方法都将结果保存在$result变量中工以后使用。如果函数运行失败将返回false。
4、获取查询结果 使用不同的函数以不同的方式将查询结果从结果对象或标识符中取出来,结果对象或标识符是访问查询返回行的关键。 通常我们要得到结果集中记录行的行数,并且使用mysqli_fetch_assoc()函数。
返回行数:$num_results = $result->num_rows;(行数保存在对象的num_rows成员变量中)或$num_results = mysqli_num_rows($result);
然后使用循环遍历每一行,在循环中调用 $row = $result->fectch_assoc();或者 $row = mysqli_fetch_assoc($result);返回该行的信息。 如果是对象返回行则每个关键词为一个属性名,每个值为属性中的相应的值;如果以资源返回则返回数组。
还有其他从结果标识符中获取结果的方法,例如:使用$row = $result->fecth_row($result);或者$row = mysqli_fetch_row($result);将结果取回 到一个列举数组中;也可以使用$row = $result->fecth_object();或者 $row = mysqli_fecth_object($result);江一行去回到一个对象中。
5、从数据库断开 先释放结果集:$result->free();或 mysqli_free_result($result);然后关闭数据库连接:$db->close()或者 mysqli_close($db); 严格的说,这并不必须,因为脚本执行完毕的时候他们将被自动关闭。
从Web查询数据库:使用Prepared语句
mysqli函数库支持prepared语句的使用。它们对于在执行大量具有不同数据的相同查询时,可以提高速度,也可以免受SQL注射风格(injection-stytle——的攻击。
prepared语句的基本思想是可以向MySQL发送一个需要执行的查询模板,然后在单独发送数据。我们可以向相同的prepared语句发送大量的相同的数据;这个特性对批量处理的插入操作来说是非常有用的。
我们一般使用一下几个步骤:
1、构造模板。已插入为例: $query = "insert into user values(?,?,?,?)";
2、使用prepared语句,构建一个语句对象或需要用来完成实际处理的资源。 $stmt = $db->prepare($query);或者mysqli_stmt_prepare($query);
3、调用$stmt->bind_param("sssd",$str1,$str3,$str3,$int4)或者mysqli_stmt_bind_param("sssd",$str1,$str3,$str3,$int4) 告诉php那些变量应该被问号所替换。第一个参数是一个格式化字符串,后面是将要被替换的变量。
3、调用$stmt->execute()或者mysqli_stmt_execute()函数,将真正运行这个query语句
对于select类型查询,可以使用$stmt->bind_result()或mysqli_stmt_bind_result()函数提供希望填充结果列的变量列表,然后每次调用 $stmt->fetch()或者mysqli_stmt_fetch()函数时,结果集下一行的值将被填充到这些绑定变量中。
使用PHP与数据库交互的其他接口
PHP支持连接到许多不同数据库的函数,包括Oracle、Microsoft SQL Server和PostgreSQL。通常,连接和查询这些火速据库的基本原理是相同的,个别 函数名称可能不同。如果希望使用PHP还没有提供支持的特殊数据库,可以使用常规的ODBC函数。
ODBC表示开放的数据库连接,他是连接数据库的标准。ODBC只具有任何函数集的优先功能,如果要求必须兼容所有的数据库,就不能使用任何数据库的特殊功能。
除了PHP附带的函数库以外,一些可供使用的数据库抽象类如MDB2允许为不同的数据库类型使用相同的函数名。但是要提前安装抽象层,例如安装PEAR MDB2抽象层。
本文标题:时空数据库查询与推理-数据时空(1)61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1