分页查询不知你是否真正的懂和PHP的正则的应用和一些性能优化
一、不废话太多 直接进入例子。
1 问题:
CREATE TABLE 收藏表(
`id` bigint(20) unsigned NOT NULL auto_increment COMMENT
'primary key'
,
`uid` bigint(20) unsigned NOT NULL
default
0 COMMENT
'uid'
,<br> `status` tinyint(3) unsigned NOT NULL
default
0 COMMENT
'status'
,
`book_id` bigint(20) unsigned NOT NULL
default
0 COMMENT
'book Id'
,
`create_time` int(11) unsigned not null
default
0 COMMENT
'create time'
,
PRIMARY KEY (`id`),
UNIQUE KEY `uid_book_id` (`uid`, `book_id`),<br> KEY `uid_status` (`uid`, `status`)
)ENGINED=Innodb Auto_increment=1
default
charset=gbk COMMENT
'用户收藏信息'
;
最容易想到的第一种分页语句是(这也是我们最容易想到的语句):
1
2
|
select distinct uid from 收藏表 order by uid desc limit 0, 10; select distinct uid from 收藏表 order by uid desc limit 11, 10; |
再高级点语句,第二种($last_min_uid表示上一次读到的最后一个uid):
1
2
|
select distinct uid from 收藏表 order by uid desc limit 10; select distinct uid from 收藏表 where uid < $last_min_uid order by uid desc limit 10; |
最高级的方式
1 select uid from 收藏表 group by uid order by uid desc limit 10;
2 select uid from 收藏表 group by uid having uid <
$last_min_uid
order by uid desc limit 10;
以上三种方式都可以实现分页获取到用户ID列表,那么区别是什么?我现在就把每一种跟大家分析下。
第一种在业务场景中,会出现丢数据的情况。——这是比较严重的情况,不予采纳。
具体的业务场景是这样的:当你读取第5页的时候,前四页的用户id列表中,假如有一页的用户ID从库中删除掉,那么你这时读到的第5页(limit 51, 10),就是原来的第6页,你会把1页的用户ID丢失掉。
第二种的第二条语句,通过explain分析,实际并没有命中唯一索引,而只是命中了一般索引,数据查询范围在7百万级别,故explain建议我们使用group by。——这个查询会有严重的性能问题。
+----+--------------+---------------+-------+-------------------------------------------------------------+-------------+----------+-------+------------+------------------------------------------------------------------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+--------------+---------------+-------+-------------------------------------------------------------+---------------------+---------+------+---------+---------------------------------------------------------------------+
| 1 | SIMPLE | ubook_room | range | uid_book_id | uid_status | 4 | NULL | 7066423 | Using where; Using index for group-by; Using temporary; Using filesort |
+----+--------------+---------------+-------+-------------------------------------------------------------+-------------+----------+-------+------------+------------------------------------------------------------------------+
第三种explain分析,数据查询范围在12万级别(跟第二种相差一个数量级),查询性能高。
+----+---------------+------------+-------+-----------------+-----------------+---------+----------+----------+-------------+
| id | select_type | table | type | possible_keys | key | key_len | ref | rows | Extra |
+----+---------------+------------+-------+-----------------+-----------------+---------+----------+----------+-------------+
| 1 | SIMPLE | 收藏表 | index | NULL | uid_book_id | 12 | NULL | 121719 | Using index |
+----+---------------+------------+-------+-----------------+-----------------+---------+----------+----------+-------------+
二、 PHP的正则:
正则表达式相信大家在很多种开发语言中都见到过,像javascript,java,php中。
$regex = '/^http:\/\/([\w.]+)\/([\w]+)\/([\w]+)\.html$/i' ; $matches = array(); if (preg_match($regex, $str, $matches)){ var_dump($matches); } echo "\n" ; |
preg_match中的$matches[0]将包含与整个模式匹配的字符串。
使用"#"定界符的代码如下.这个时候对"/"就不转义!
$matches = array(); if (preg_match($regex, $str, $matches)){ var_dump($matches); } echo "\n" ; |
¤ 修饰符:用于改变正则表达式的行为。
我们看到的('/^http:\/\/([\w.]+)\/([\w]+)\/([\w]+)\.html/i')中的最后一个"i"就是修饰符,表示忽略大小写,还有一个我们经常用到的是"x"表示忽略空格。
贡献代码:
$regex = '/HELLO/' ; $str = 'hello word' ; $matches = array (); if (preg_match( $regex , $str , $matches )){ echo 'No i:Valid Successful!' , "\n" ; } if (preg_match( $regex . 'i' , $str , $matches )){ echo 'YES i:Valid Successful!' , "\n" ; } |
¤ 字符域:[\w]用方括号扩起来的部分就是字符域。
¤ 限定符:如[\w]{3,5}或者[\w]*或者[\w]+这些[\w]后面的符号都表示限定符。现介绍具体意义。
{3,5}表示3到5个字符。{3,}超过3个字符,{,5}最多5个,{3}三个字符。
* 表示0到多个
+ 表示1到多个。
¤ 脱字符号
^:
> 放在字符域(如:[^\w])中表示否定(不包括的意思)——“反向选择”
> 放在表达式之前,表示以当前这个字符开始。(/^n/i,表示以n开头)。
注意,我们经常管"\"叫"跳脱字符"。用于转义一些特殊符号,如".","/"
$regex = '/(?<=c)d(?=e)/' ; /* d 前面紧跟c, d 后面紧跟e*/ $str = 'abcdefgk' ; $matches = array (); if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
否定意义:
$regex = '/(?<!c)d(?!e)/' ; /* d 前面不紧跟c, d 后面不紧跟e*/ $str = 'abcdefgk' ; $matches = array (); if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
$regex = '/HE(?=L)LO/i' ; $str = 'HELLO' ; $matches = array (); if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
打印不出结果!
$regex = '/HE(?=L)LLO/i' ; $str = 'HELLO' ; $matches = array (); if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
能打印出结果!
说明:(?=L)意思是HE后面紧跟一个L字符。但是(?=L)本身不占字符,要与(L)区分,(L)本身占一个字符。
$regex = '/^(Chuanshanjia)[\w\s!]+\1$/' ; $str = 'Chuanshanjia thank Chuanshanjia' ; $matches = array (); if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
$regex = '/(?P<author>chuanshanjia)[\s]Is[\s](?P=author)/i' ; $str = 'author:chuanshanjia Is chuanshanjia' ; $matches = array (); if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
运行结果
惰性匹配(记住:会进行两部操作,请看下面的原理部分)
格式:限定符?
原理:"?":如果前面有限定符,会使用最小的数据。如“*”会取0个,而“+”会取1个,如过是{3,5}会取3个。
先看下面的两个代码:
代码1.
<?php $regex = '/heL*/i' ; $str = 'heLLLLLLLLLLLLLLLL' ; if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
结果1.
代码2
<?php $regex = '/heL*?/i' ; $str = 'heLLLLLLLLLLLLLLLL' ; if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
结果2
代码3,使用“+”
<?php $regex = '/heL+?/i' ; $str = 'heLLLLLLLLLLLLLLLL' ; if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
结果3
代码4,使用{3,5}
<?php $regex = '/heL{3,10}?/i' ; $str = 'heLLLLLLLLLLLLLLLL' ; if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
结果4
$regex = '/ ^host=(?<!\.)([\d.]+)(?!\.) (?#主机地址) \| ([\w!@#$%^&*()_+\-]+) (?#用户名) \| ([\w!@#$%^&*()_+\-]+) (?#密码) (?!\|)$/ix'; $str = 'host=192.168.10.221|root|123456' ; $matches = array (); if (preg_match( $regex , $str , $matches )){ var_dump( $matches ); } echo "\n" ; |
特殊字符 | 解释 |
* | 0到多次 |
+ | 1到多次还可以写成{1,} |
? | 0或1次 |
. | 匹配除换行符外的所有单个的字符 |
\w | [a-zA-Z0-9_] |
\s | 空白字符(空格,换行符,回车符)[\t\n\r] |
\d | [0-9] |
三、PHP一些性能优化问题
1
2
3
4
5
6
7
8
9
10
11
|
class dog { public $name = '' ; public function setName( $name ) { $this ->name = $name ; } public function getName() { return $this ->name; } } |
注意:setName()和getName()除了存储和返回name属性外,没做任何工作。
1
2
3
|
$rover = new dog(); $rover ->setName( 'rover' ); echo $rover ->getName(); |
直接设置和访问name属性,性能能提升100%,而且也能缩减开发时间!
1
2
3
|
$rover = new dog(); $rover ->name = 'rover' ; echo $rover ->name; |
1
2
|
$description = strip_tags ( $_POST [ 'description' ]); echo $description ; |
1
|
echo strip_tags ( $_POST [ 'description' ]); |
1
2
3
4
|
foreach ( $userList as $user ) { $query = 'INSERT INTO users (first_name,last_name) VALUES("' . $user [ 'first_name' ] . '", "' . $user [ 'last_name' ] . '")' ; mysql_query( $query ); } |
过程:
1
|
INSERT INTO users (first_name,last_name) VALUES( "John" , "Doe" ) |
替换这种循环方案,你能够拼接数据成为一个单一的数据库操作。
1
2
3
4
5
6
|
$userData = array (); foreach ( $userList as $user ) { $userData [] = '("' . $user [ 'first_name' ] . '", "' . $user [ 'last_name' ] . '")' ; } $query = 'INSERT INTO users (first_name,last_name) VALUES' . implode( ',' , $userData ); mysql_query( $query ); |
过程:
1
|
INSERT INTO users (first_name,last_name) VALUES( "John" , "Doe" ),( "Jane" , "Doe" )... |
- PHP Memcache module
- Smarty templating engine
- http://3v4l.org --- 分析各个版本间的代码执行效率,非常不错的网站
- http://www.php-internals.com/ ———研究php内核的网站!
分页查询不知你是否真正的懂和PHP的正则的应用和一些性能优化的更多相关文章
- elasticserach数据库深度分页查询的原理
深度分页存在的问题 https://segmentfault.com/a/1190000019004316?utm_source=tag-newest 在实际应用中,分页是必不可少的,例如,前端页面展 ...
- EntityFramework之原始查询及性能优化(六)
前言 在EF中我们可以通过Linq来操作实体类,但是有些时候我们必须通过原始sql语句或者存储过程来进行查询数据库,所以我们可以通过EF Code First来实现,但是SQL语句和存储过程无法进行映 ...
- Mybatis+SpringMVC实现分页查询(附源码)
Maven+Mybatis+Spring+SpringMVC实现分页查询(附源码) 一.项目搭建 关于项目搭建,小宝鸽以前写过一篇Spirng+SpringMVC+Maven+Mybatis+MySQ ...
- Java GUI+mysql+分页查询
1.要求 : 创建一个学生信息管理数据库 2.实现分页查询 代码如下: a)学生实体类: /** * @author: Annie * @date:2016年6月23日 * @description: ...
- Maven+Mybatis+Spring+SpringMVC实现分页查询
转载:http://www.cnblogs.com/zhangtan/p/5846955.html 一.项目搭建 关于项目搭建,小宝鸽以前写过一篇Spirng+SpringMVC+Maven+Myba ...
- Maven+Mybatis+Spring+SpringMVC实现分页查询(附源代码)
以下小宝鸽将分享一篇Mybatis分页功能的博文,以下将给出具体的步骤.跟着博主的节奏肯定能实现.另外最后还会附上整个project的源代码.假设是没有使用过maven的猿友可自行下载相关的jar包就 ...
- tp框架使用心得(六)——分页查询
http://baijiahao.baidu.com/s?id=1578482537511010805&wfr=spider&for=pc 在用thinkphp中,对于新手手册中还是有 ...
- 如何用Mybatis逆向工程实现分页查询(更改生成的Example)
如何用Mybatis逆向工程实现分页查询 一个很简单的方法,如果要mysql实现分页查询的话,执行下述语句即可 select * from table limit (offset)5,(limit) ...
- JdbcTemplate+PageImpl实现多表分页查询
一.基础实体 @MappedSuperclass public abstract class AbsIdEntity implements Serializable { private static ...
随机推荐
- Java基础学习 —— 对象的克隆
对象的克隆分为对象的浅克隆和深克隆 一.对象的浅克隆 注意事项: 1.如果一个对象需要调用clone的方法克隆,那么该对象必须要实现Cloneable接口 2.Cloneable对象只是一个标识对象, ...
- Mac Intellij Debug 模式
前言:本文的核心是记录debug的使用,与具体的操作系统无关. 1.什么是Debug Debug是程序的一种运行模式.用来发掘程序的走向,以及程序在运行过程中参数的变化. 2.Debug的作用 deb ...
- java 多线程(0) Java线程
线程 线程是系统调度的基本单元,每当创建一个进程时,会有许多的线程,也叫轻量级进程,在一个进程中拥有多个线程,各自都有自己的计数器,堆和局部变量属性,并且能够分享内存变量. 为什么要使用多线程 1. ...
- HTML的基本标签及语法
一.HTML基本标签head部分 HTML文档的基本结构 <!DOCTYPE html> <html> <head> <meta charset=" ...
- 结对编程1-四则运算GUI实现(58、59)
题目描述 我们在个人作业1中,用各种语言实现了一个命令行的四则运算小程序.进一步,本次要求把这个程序做成GUI(可以是Windows PC 上的,也可以是Mac.Linux,web,手机上的),成为一 ...
- 团队作业4---第一次项目冲刺(ALpha)版本 第五天
一.Daily Scrum Meeting照片 二.燃尽图 三.项目进展 a.完成所有基础功能 b.正在进行测试调试 四.困难与问题 1.根据测试需求功能,部分基础功能不能实现,性能不达标,后续已完成 ...
- 201521123115 《Java程序设计》第1周学习总结
1. 本周学习总结 之前一直没有用心学,这周上课虽然认真但还是太多不懂加上还要补考没有时间来消化所以很多都是囫囵吞枣,希望能够赶快补上把. 知道了java的前世今生,JVM/JRE/JDK,JVM就是 ...
- 201521123064 《Java程序设计》第10周学习总结
1. 本章学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常与多线程相关内容. ① 定义Thread类的子类,覆盖Thread类的run()方法,然后创建该子类的实例(一般不用该方法,开销 ...
- 多线程面试题系列(12):多线程同步内功心法——PV操作上
上面的文章讲解了在Windows系统下实现多线程同步互斥的方法,为了提高在实际问题中分析和思考多个线程之间同步互斥问题的能力,接下来将讲解PV操作,这也是操作系统中的重点和难点.本文将会先简要介绍下P ...
- informix服务端口和oralce服务端口
查找informix的服务端口1>>more .profile 找到: INFORMIXDIR=/home/informix INFORMIXSERVER=aaaa2>>cd ...