mysql 查询优化建议
1.用变量替代sql函数,大多数的MySQL服务器都开启了查询缓存。这是提高性最有效的方法之一,而且这是被MySQL的数据库引擎处理的。当有很多相同的查询被执行了多次的时候,这些查询结果会被放到一个缓存中。
// 查询缓存不开启 $r = mysql_query("SELECT username FROM user WHERE signup_date >= CURDATE()"); // 开启查询缓存 $today = date("Y-m-d"); $r = mysql_query("SELECT username FROM user WHERE signup_date >= '$today'");
使用sql自带的函数不会开启查询优化,建议用变量替代sql函数。
2.用EXPLAIN关键字解析sql语句,方便自己优化sql结构。
EXPLAIN select u.name,g.com from g left join u on u.id=g.id where g.id between 1 and 10
比如:
通过比较发现u表的主键没有定义,可根据业务逻辑进行修改。
3.只用一条数据的时候加上limit 1,只返回一条记录的时候因为用到了fetch游标或者检查影响的行数,会造成一定资源的浪费,加上limit 1使mysql引擎停止向下查找。
4.为搜索字段加索引,索引不一定加在主键或者唯一字段,可以是经常用到的字段。
比如:
5.使用join和in将连接字段索引还有修改join_buffer_size的值,使用join和in进行连接时主要是一种nest loop算法,为了解决避免重复读取数据加入了缓存的概念,这就是join buffer(Blocked Nested Loop),即连接缓冲。
set session join_buffer_size=128;
6.千万不要用order by rand();
// 千万不要这样做: $r = mysql_query("SELECT username FROM user ORDER BY RAND() LIMIT 1"); // 这要会更好: $r = mysql_query("SELECT count(*) FROM user"); $d = mysql_fetch_row($r); $rand = mt_rand(0,$d[0] - 1); $r = mysql_query("SELECT username FROM user LIMIT $rand, 1");
7.不要用select *;
从数据库中读取的数据越多那么查询的速度就越慢,如过数据库服务器和应用服务器不再同一服务器上还会加深网络传输的负担。
8.建表最好每个表一个id,而且数据类型是int型,并设置主键;
千万不要用字符型字段作为主键,会加大数据库的负担。
业务的数据结构对于表的关联最好围绕id设计。
9.使用enum而不是varchar,enum是个相当快而且紧凑的数据类型,他保存的是tinyint,但是展示的是字符串,这些字段作为选项列表就很完美了。
10从procedure analy()获取建议,
procedure analy(),可以分析表的结构和实际数据,并提供建议。
procedure analyse();语法如下 select column from table_name procedure analyse(); 以下引用一段文章: PROCEDURE ANALYSE 通过分析select查询结果对现有的表的每一列给出优化的建议。 PROCEDURE ANALYSE的语法如下: SELECT ... FROM ... WHERE ... PROCEDURE ANALYSE([max_elements,[max_memory]]) max_elements (默认值256) analyze查找每一列不同值时所需关注的最大不同值的数量. analyze还用这个值来检查优化的数据类型是否该是ENUM,如果该列的不同值的数量超过了 max_elements值ENUM就不做为建议优化的数据类型。 max_memory (默认值8192) analyze查找每一列所有不同值时可能分配的最大的内存数量
在phpmyadmin里,你可以在查看表时,点击 “Propose table structure” 来查看这些建议。
11.尽可能使用not null
12.Prepared Statements
个人理解是预编译,通过预编译并绑定变量,检查是否有sql注入提高安全性,同时同高性能。
// 创建 prepared statement if ($stmt = $mysqli->prepare("SELECT username FROM user WHERE state=?")) { // 绑定参数 $stmt->bind_param("s", $state); // 执行 $stmt->execute(); // 绑定结果 $stmt->bind_result($username); // 移动游标 $stmt->fetch(); printf("%s is from %s\n", $username, $state); $stmt->close(); }
13. 把IP地址存成 UNSIGNED INT
很多程序员都会创建一个 VARCHAR(15) 字段来存放字符串形式的IP而不是整形的IP。如果你用整形来存放,只需要4个字节,并且你可以有定长的字段。而且,这会为你带来查询上的优势,尤其是当你需要使用这样的WHERE条件:IP between ip1 and ip2。
我们必需要使用UNSIGNED INT,因为 IP地址会使用整个32位的无符号整形。
而你的查询,你可以使用 INET_ATON() 来把一个字符串IP转成一个整形,并使用 INET_NTOA() 把一个整形转成一个字符串IP。在PHP中,也有这样的函数 ip2long() 和 long2ip()。
1 $r = "UPDATE users SET ip = INET_ATON('{$_SERVER['REMOTE_ADDR']}') WHERE user_id = $user_id";
还没看完,今天难道这明天继续网址:http://www.jb51.net/article/24392.htm