??xml version="1.0" encoding="utf-8" standalone="yes"?>人妻精品久久无码专区精东影业,国产精品女同久久久久电影院,国产精品久久久99http://www.shnenglu.com/ispfcn/archive/2006/04/06/5110.html~程之道~程之道Thu, 06 Apr 2006 06:29:00 GMThttp://www.shnenglu.com/ispfcn/archive/2006/04/06/5110.htmlhttp://www.shnenglu.com/ispfcn/comments/5110.htmlhttp://www.shnenglu.com/ispfcn/archive/2006/04/06/5110.html#Feedback0http://www.shnenglu.com/ispfcn/comments/commentRss/5110.htmlhttp://www.shnenglu.com/ispfcn/services/trackbacks/5110.htmlhttp://www.unix-cd.com/unixcd12/article_view.asp?id=4138
贴一D以前在windows上用mysql的代码?br />
 1#include <stdio.h>
 2#include <string.h>
 3#include <winsock2.h>
 4#include "mysql.h"
 5
 6#pragma comment(lib,"libmySQL.lib")
 7
 8void main(){
 9   MYSQL *mysql;
10   MYSQL_RES *res;
11   MYSQL_ROW row;
12   char *query;
13   int t,r;
14   
15
16   mysql=mysql_init(mysql);
17   if (!mysql_real_connect(mysql,"localhost","root","","ceshi",0,NULL,0))
18   {
19       printf( "Error connecting to database: %s\n",mysql_error(mysql));
20   }

21   else
22       printf("Connected\n");
23
24   query="Insert Into admin(username,password) values('whoami','iampf')";
25   t=mysql_real_query(mysql,query,(unsigned int)strlen(query));
26   if(t)
27   {
28       printf("Insert Error:%s\n",mysql_error(mysql));
29   }

30
31   query="select * from admin";
32   t=mysql_real_query(mysql,query,(unsigned int) strlen(query));
33   if (t)
34   {
35      printf("Error making query: %s\n",
36              mysql_error(mysql));
37   }

38   else printf("Query made\n");
39   res=mysql_use_result(mysql);
40   for(r=0;r<mysql_field_count(mysql);r++){
41           row=mysql_fetch_row(res);
42           if(row<0break;
43           for(t=0;t<mysql_num_fields(res);t++){
44                   printf("%s ",row[t]);
45           }

46           printf("\n");
47   }

48   mysql_close(mysql);
49}

50
51


~程之道 2006-04-06 14:29 发表评论
]]>
Windows上的MySQL UDF开?/title><link>http://www.shnenglu.com/ispfcn/archive/2006/04/06/5075.html</link><dc:creator>~程之道</dc:creator><author>~程之道</author><pubDate>Thu, 06 Apr 2006 04:02:00 GMT</pubDate><guid>http://www.shnenglu.com/ispfcn/archive/2006/04/06/5075.html</guid><wfw:comment>http://www.shnenglu.com/ispfcn/comments/5075.html</wfw:comment><comments>http://www.shnenglu.com/ispfcn/archive/2006/04/06/5075.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ispfcn/comments/commentRss/5075.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ispfcn/services/trackbacks/5075.html</trackback:ping><description><![CDATA[ <p>l于发现了篇不错的Mysql开发的文章<br />曾以为Windows版本的MySQL存在不能使用UDF的BUG诸提交了一个bug报告。不q?br />g发现是我搞错了,MySQL的技术支持h员给了非常完的解答Q同大家分n<br />一下。下Ҏ原文回复 :)<br /><br />Sorry this isn't a bug.<br />Below I pasted a sample I did sometime ago for another user:<br /><br />Ok. Assuming you have VC++ and the source distribution and a server<br />running,<br />I will create a UDF that returns a name:<br /><br />Note: the sample is ugly, but the purpose here is to show you how<br />to handle the UDF.<br /><br />- Open the mysqld.dsw workspace.<br />- Add New project to the workspace<br />- Project name: my_udf<br />- Select Win32 Dynamic-Link Library<br />- Click OK<br />- Select An Empty DLL project<br />- Click Finish<br />- Click OK<br />- Add a new file called my_udf.cpp to the project:<br /><br />#include <stdlib.h><br />#include <winsock.h><br />#include <mysql.h><br /><br />extern "C" {<br />char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,<br />char *error);<br />}<br /><br />char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,<br />char *error)<br />{<br />char * me = "my name";<br /><br />return me;<br />}<br /><br />- Type Ctrl+N for to create a new file.<br />- Select text type<br />- File name: my_udf.def<br />- Edit the above file with the below contents:<br />LIBRARY UDF_EXAMPLE<br />DESCRIPTION 'Example Using UDF with VC++'<br />VERSION 1.0<br />EXPORTS<br />my_name<br /><br />- Right Click the my_udf project and select Settings<br />- Click the C/C++ tab<br />- Select General in the Category Combo<br />- Add the macro HAVE_DLOPEN to the PreProcessor definition<br />- Select Preprocessor in the Category Combo<br />- Add the include path to the text box: Additional Include directories<br />e.g: ../include<br />- Press F7 for to build the DLL.<br /><br />- Copy the my_udf.dll to the environment path directory:<br />\winnt\system32 for example.<br /><br />- Start the mysql client and issue:<br /><br />C:\mysql-udf\bin>mysql -uroot -p<br />Enter password:<br />Welcome to the MySQL monitor. Commands end with ; or \g.<br />Your MySQL connection id is 2 to server version: 3.23.52-max-nt<br /><br />Type 'help;' or '\h' for help. Type '\c' to clear the buffer.<br /><br />mysql> CREATE FUNCTION my_name RETURNS STRING SONAME "my_udf.dll";<br />Query OK, 0 rows affected (0.08 sec)<br /><br />mysql> select my_name();<br /><br />mysql> drop function my_name;<br />Query OK, 0 rows affected (0.00 sec)<br /><br />画蛇添的作下简要中文说明?br /><br />抱歉Q这q不是一个bug。下面我_脓一个以前ؓ某个客户做的例,假设你有?br />VC++,源码分发Qƈ且有一个正常运行的MySQL服务器?br /><br />我将创徏一个UDF它将一个名字:<br />注意Q例子非常简陋,目的是让你了解该如何处理手头的UDF?br /><br />- 打开 mysqld.dsw 工作区?br />- d新项目到q个工作?br />- Project name: my_udf // 目名称:my_udf<br />- 选择 Win32 Dynamic-Link Library // Win32动态连接库<br />- 点击 OK<br />- 选择 An Empty DLL project // 一个空DLL目<br />- 点击 Finish<br />- 点击 OK<br />- d新文?my_udf.cpp 到项目中:<br />#include <stdlib.h><br />#include <winsock.h><br />#include <mysql.h><br /><br />extern "C" {<br />char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,<br />char *error);<br />// 兼容C<br />}<br /><br />char *my_name(UDF_INIT *initid, UDF_ARGS *args, char *is_null,<br />char *error)<br />{<br />char * me = "my name";<br /><br />return me;<br />// 调用此UDF返?my name<br />}<br />- ?Ctrl+N 来创Z个新文g?br />- 选择 text cd<br />- File name: my_udf.def file://文g名:my_udf.def<br />- 按照下边的内容编辑文件?br />LIBRARY UDF_EXAMPLE<br />DESCRIPTION 'Example Using UDF with VC++'<br />VERSION 1.0<br />EXPORTS<br />my_name<br /><br />- 叛_my_udf目q择Settings<br />- ?C/C++ 选项?br />- 选择 General<br />- d?HAVE_DLOPE 到预处理器定?br />- 选择 Preprocessor<br />- d头文件\? Additional Include directories<br />例如: ../include<br />- ?F7 ȝ译成 DLL.<br /><br />- 复制 my_udf.dll 到环境变量path定义q的目录<br />比如 \winnt\system32 ?br /><br />- 打开mysql客户?br /><br />C:\mysql-udf\bin>mysql -uroot -p<br />Enter password:<br />Welcome to the MySQL monitor. Commands end with ; or \g.<br />Your MySQL connection id is 2 to server version: 3.23.52-max-nt<br /><br />Type 'help;' or '\h' for help. Type '\c' to clear the buffer.<br /><br />mysql> CREATE FUNCTION my_name RETURNS STRING SONAME "my_udf.dll";<br />Query OK, 0 rows affected (0.08 sec)<br /><br />mysql> select my_name();<br /><br />mysql> drop function my_name;<br />Query OK, 0 rows affected (0.00 sec)<br /><br /><br />ok!Ƣ迎大家来MySQL板交UDF设计l验Q我的电子邮件是HeartIcy@163.comQ?br />手机13706410308。同Ӟ我们MySQL板准备开始系l化持箋性翻译MySQL文档Q?br />希望大家多多支持共同完成q一目?br /><br />HeartIcy<br />2003q??7日于中国南<br /></p> <img src ="http://www.shnenglu.com/ispfcn/aggbug/5075.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ispfcn/" target="_blank">~程之道</a> 2006-04-06 12:02 <a href="http://www.shnenglu.com/ispfcn/archive/2006/04/06/5075.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>提高mysql性能的方?/title><link>http://www.shnenglu.com/ispfcn/archive/2006/04/04/4998.html</link><dc:creator>~程之道</dc:creator><author>~程之道</author><pubDate>Tue, 04 Apr 2006 08:42:00 GMT</pubDate><guid>http://www.shnenglu.com/ispfcn/archive/2006/04/04/4998.html</guid><wfw:comment>http://www.shnenglu.com/ispfcn/comments/4998.html</wfw:comment><comments>http://www.shnenglu.com/ispfcn/archive/2006/04/04/4998.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/ispfcn/comments/commentRss/4998.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/ispfcn/services/trackbacks/4998.html</trackback:ping><description><![CDATA[一、问题的提出<br />在应用系l开发初期,׃开发数据库数据比较,对于查询SQL语句Q复杂视囄的编写等体会不出SQL语句各种写法的性能优劣Q但是如果将应用pȝ提交实际应用后,随着数据库中数据的增加,pȝ的响应速度成为目前系l需要解决的最主要的问题之一。系l优化中一个很重要的方面就是SQL语句的优化。对于v量数据,劣质SQL语句和优质SQL语句之间的速度差别可以辑ֈ上百倍,可见对于一个系l不是简单地能实现其功能可Q而是要写出高质量?SQL语句Q提高系l的可用性?br /><br />在多数情况下QOracle使用索引来更快地遍历表,优化器主要根据定义的索引来提高性能。但是,如果在SQL语句的where子句中写的SQL 代码不合理,׃造成优化器删ȝ引而用全表扫描,一般就q种SQL语句是所谓的劣质SQL语句。在~写SQL语句时我们应清楚优化器根据何U原则来删除索引Q这有助于写出高性能的SQL语句?br /><br />二、SQL语句~写注意问题<br />下面某些SQL语句的where子句~写中需要注意的问题作详l介l。在q些where子句中,即某些列存在烦引,但是׃~写了劣质的SQLQ系l在q行该SQL语句时也不能使用该烦引,而同样用全表扫描,q就造成了响应速度的极大降低?br /><br />1. IS NULL ?IS NOT NULL<br />不能用null作烦引,M包含null值的列都不会被包含在烦引中。即使烦引有多列q样的情况下Q只要这些列中有一列含有nullQ该列就会从索引中排除。也是说如果某列存在空|即对该列徏索引也不会提高性能?br /><br />M在where子句中用is null或is not null的语句优化器是不允许使用索引的?br /><br />2. 联接?br /><br />对于有联接的列,即最后的联接gؓ一个静态|优化器是不会使用索引的。我们一h看一个例子,假定有一个职工表QemployeeQ,对于一个职工的姓和名分成两列存放(FIRST_NAME和LAST_NAMEQ,现在要查询一个叫比尔.克林(Bill ClitonQ的职工?br /><br />下面是一个采用联接查询的SQL语句Q?br /><br />select * from employss<br />where<br />first_name||''||last_name ='Beill Cliton' <br /><br />上面q条语句完全可以查询出是否有Bill Clitonq个员工Q但是这里需要注意,pȝ优化器对Zlast_name创徏的烦引没有用?br /><br />当采用下面这USQL语句的编写,Oraclepȝ可以采用基于last_name创徏的烦引?br /><br />Select * from employee<br />where<br />first_name ='Beill' and last_name ='Cliton' <br /><br />遇到下面q种情况又如何处理呢Q如果一个变量(nameQ中存放着Bill Clitonq个员工的姓名,对于q种情况我们又如何避免全E遍历,使用索引呢?可以使用一个函敎ͼ变量name中的姓和名分开可以了Q但是有一炚w要注意,q个函数是不能作用在索引列上。下面是SQL查询脚本Q?br /><br />select * from employee<br />where<br />first_name = SUBSTR('&&name',1,INSTR('&&name',' ')-1)<br />and<br />last_name = SUBSTR('&&name',INSTR('&&name?' ')+1) <br /><br />3. 带通配W(%Q的like语句<br /><br />同样以上面的例子来看q种情况。目前的需求是q样的,要求在职工表中查询名字中包含cliton的h。可以采用如下的查询SQL语句Q?br /><br />select * from employee where last_name like '%cliton%' <br /><br />q里׃通配W(%Q在搜寻词首出现Q所以Oraclepȝ不用last_name的烦引。在很多情况下可能无法避免这U情况,但是一定要心中有底Q通配W如此用会降低查询速度。然而当通配W出现在字符串其他位|时Q优化器p利用索引。在下面的查询中索引得到了用:<br /><br />select * from employee where last_name like 'c%' <br /><br />4. Order by语句<br /><br />ORDER BY语句军_了Oracle如何返回的查询l果排序。Order by语句对要排序的列没有什么特别的限制Q也可以函数加入列中(象联接或者附加等Q。Q何在Order by语句的非索引Ҏ者有计算表达式都降低查询速度?br /><br />仔细查order by语句以找出非索引Ҏ者表辑ּQ它们会降低性能。解册个问题的办法是重写order by语句以用烦引,也可以ؓ所使用的列建立另外一个烦引,同时应绝寚w免在order by子句中用表辑ּ?br /><br />5. NOT<br /><br />我们在查询时l常在where子句使用一些逻辑表达式,如大于、小于、等于以及不{于{等Q也可以使用andQ与Q、orQ或Q以及notQ非Q。NOT可用来对M逻辑q算W号取反。下面是一个NOT子句的例子:<br /><br />... where not (status ='VALID') <br /><br />如果要用NOTQ则应在取反的短语前面加上括Pq在短语前面加上NOTq算W。NOTq算W包含在另外一个逻辑q算W中Q这是不等于(<>Q运符。换句话_即不在查询where子句中显式地加入NOT词,NOT仍在q算W中Q见下例Q?br /><br />... where status <>'INVALID' <br /><br />再看下面q个例子Q?br /><br />select * from employee where salary<>3000; <br /><br />对这个查询,可以改写Z使用NOTQ?br /><br />select * from employee where salary<3000 or salary>3000; <br /><br />虽然q两U查询的l果一P但是W二U查询方案会比第一U查询方案更快些。第二种查询允许Oracle对salary列用烦引,而第一U查询则不能使用索引?br /><br />6. IN和EXISTS<br /><br />有时候会一列和一pd值相比较。最单的办法是在where子句中用子查询。在where子句中可以用两U格式的子查询?br /><br />W一U格式是使用IN操作W:<br /><br />... where column in(select * from ... where ...); <br /><br />W二U格式是使用EXIST操作W:<br /><br />... where exists (select 'X' from ...where ...); <br /><br />我相信绝大多Ch会用第一U格式,因ؓ它比较容易编写,而实际上W二U格式要q比W一U格式的效率高。在Oracle中可以几乎将所有的IN操作W子查询改写Z用EXISTS的子查询?br /><br />W二U格式中Q子查询以‘select 'X'开始。运用EXISTS子句不管子查询从表中抽取什么数据它只查看where子句。这样优化器׃必遍历整个表而仅Ҏ索引可完成工作Q这里假定在where语句中用的列存在烦引)。相对于IN子句来说QEXISTS使用相连子查询,构造v来要?IN子查询困难一些?br /><br />通过使用EXISTQOraclepȝ会首先检查主查询Q然后运行子查询直到它找到第一个匹配项Q这p省了旉。Oraclepȝ在执行IN子查询时Q首先执行子查询Qƈ获得的l果列表存放在在一个加了烦引的临时表中。在执行子查询之前,pȝ先将L询挂P待子查询执行完毕Q存攑֜临时表中以后再执行主查询。这也就是用EXISTS比用IN通常查询速度快的原因?br /><br />同时应尽可能使用NOT EXISTS来代替NOT INQ尽二者都使用了NOTQ不能用烦引而降低速度Q,NOT EXISTS要比NOT IN查询效率更高?br /><img src ="http://www.shnenglu.com/ispfcn/aggbug/4998.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/ispfcn/" target="_blank">~程之道</a> 2006-04-04 16:42 <a href="http://www.shnenglu.com/ispfcn/archive/2006/04/04/4998.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>如何~写高效的MySQL应用http://www.shnenglu.com/ispfcn/archive/2006/04/04/4992.html~程之道~程之道Tue, 04 Apr 2006 06:10:00 GMThttp://www.shnenglu.com/ispfcn/archive/2006/04/04/4992.htmlhttp://www.shnenglu.com/ispfcn/comments/4992.htmlhttp://www.shnenglu.com/ispfcn/archive/2006/04/04/4992.html#Feedback0http://www.shnenglu.com/ispfcn/comments/commentRss/4992.htmlhttp://www.shnenglu.com/ispfcn/services/trackbacks/4992.html 

MySQL对于成ؓ一个非常快速的数据库服务器有着当之无愧的名壎ͼ它也非常Ҏ讄和用。随着它作为网站后端数据库得声望日增,其效果在d开始有明显提高。但是很多MySQL用户更多地知道如何创Z个数据库q编写对它的查询。就像成千上万的人通过载闲暇时用Linux做实验来学习Unix那样Q很多h通过玩MySQL学习关系数据库。这些MySQL新手的大多数既没有关pL据库理论的背景,又没有时间阅读MySQL手册全文?i> 

因此Q我们决定研I某些方法,你可以用针对优化性能来调节MySQL。在d本文后,你将理解一些帮助你设计你的MySQL数据库和查询的技术,值得你的应用很有效率。我们将假定你熟悉MySQL和SQL基础Q但不假定你有这两方面的q博知识?/p>

只存储你需要的信息

q听上去是常识,但h们常帔R取“厨房下水道”的方式q行数据库设计。他们认为可能项要得每样东西都要存储q设计数据库保存所有者这些数据。你需要对你的需求现实些Qƈ定取确实需要什么信息。你常常能随意生一些数据而不把它存在数据库表中。在q种情况下,从一个应用开发者的角度看也有道理这样做?/p>

例如Q在U目录的产品表可能包含各U品的名称、介l、尺寸、重量和h。除了h|你可能想存储每个目相关的税和运输成本。但实际上不必这样做。首先税和运输成本可以方便地Q由你的应用或MySQLQ计出来。其ơ,如果E和q输成本改变了,你可能必ȝ写必要的查询更新每个产品记录中的E和q输的费率?/p>

有时Z认ؓq太难不能在以后往数据库表中加入字D,所以他们感觉不得不定义可能多的列。这是明昄概念错误。在MySQL中,你可以用ALTER TABLE命o方便C改表定义以适应你改变的需求?/p>

例如Q如果你H然认识C需要给你的产品表增加一个别列Q可能你惛_许用户在你的目录中给产品评Q,你可以这样做Q?/p>

ALTER TABLE products ADD rank INTEGER   

q给你的产品表增加了一个整数类型的U别列,你能用ALTER TABLE做什么的完整介绍参见MySQL手册?/p>

只要求你需要的东西--要清?/p>

像说“只存储你需要的东西”那Pq可能看来是常识Q但q一点常常被忽视Qؓ什么呢Q因为在一个应用开发时Q需求经常改变,所以很多查询最l看来是q样Q?/p>

SELECT * FROM sometable   

当你不能肯定你将需要哪一列时Q要求所有列明显是最省力的事情,然而随着你的表不断增大和修改Q这可能变成一个性能问题。最好是在你的最初开发完成后再花些时间ƈ定你真正从你的查询中需要什么:

SELECT name, rank, description FROM products 
  

q带来了一个相关的观点Q即代码l护比性能更重要。大多数变成语言QPerl、Python、PHP、Java{)允许通过字段名和数字~号讉K一条查询的l果Q这意味着你可以访问命名字D|字段Q都可以得到相同的数据?/p>

长期看,最好用列名而不是其~号位置Qؓ什么?因ؓ一个表中或一条查询中地列的相对位|可以改变。它们在表中可能因ؓ重复使用ALTER TABLE而改变,它们在查询中因重写了查询而忘记更新应用逻辑来匹配而改变?/p>

当然Q你仍然需要小心改变列名!但如果你使用列名而非标号位置Q如列名改变Q你可以用grep搜烦源代码或使用~辑器的搜烦能力查找你需要修改的代码?/p>

规范化你的表l构

如果你以前从未听说过“数据规范化”,不要x。规范化可能是一个复杂的专题Q你可以从只理解最基本的规范化概念中正真正L?/p>

理解它的最Ҏ的方法是认ؓ你的表是一个电子报表。如果你想以一个报表跟t你的CD收藏Q你可以如图Q种那样q行设计Q?/p>

图1

album                      track1        track2             track10
-----                      ------        ------             -------
Billboard Top Hits - 1984  Loverboy      Shout              St. Elmo's Fire
                           (Billy Ocean) (Tears for Fears) (John Parr)

 

q看上去很合理。大多数CD只有10首曲子,对否Q不然。如果你拥有一张有100首曲子的CD且几张超q?0首改怎么办。这意味着用这U方法,在极端的情况下,你将需要一个非常宽的表|或一个超q?00个字D늚表)来保存所有的数据?/p>

规范化表l构的目标是低쀜空单元”的数量最,在上qCD表的情况下,如果你允许CD可能包含100首曲子,你会有很多这LI单元。不你何时处理可能扩展到类DCD表那h量的字段列表Q它是你需要将你的数据分割?个或更多表的标志Q然后你一赯问ƈ获得你需要的数据?/p>

很多关系数据库的新手不真正知道关pL据库理pȝ中关pL什么。简单地_像一l信息存在可以基于共性数据联l(JOINQ在一L不同表中Q很不幸Q这听上L学术化和含糊Q但CD数据库提Z一个具体情况,我们可以研究如何规范数据?/p>

每个CD列表有一个固定的属性(标题、艺术家、年份、分c)集和一个不定的属性(曲目表)集的理解l了我们一些如何分成成能相互关联的表的思\?/p>

你可以创Z个所有专辑及其固定属性的表,另一个包含这些专辑的所有曲目的表。这样不是水qx考(像表|Q你垂直思?-好像你创徏列表而不是行--q徏立一个如?的表l构Q?br />r_2.jpg
专辑的编PMySQL镜自动ؓ你生成,因ؓ我们在列上用了AUTO_INCREMENT属性)兌不同曲目Cl定专辑Qtracks表中的album_id字段匚w专辑表中的一个id。这栯获得l定专辑的所有曲目,你应该用如下查询Q?/font>

 SELECT tracks.num, tracks.name
   FROM albums, tracks
   WHERE albums.title = 'Billboard Top Hits - 1984'
   AND albums.id = tracks.album_id
  

该结构即灉|又有效。灵zL来自你可以在以后将数据加入pȝ而不必重C已完整的工作的事实。例如,如果你想增加每一张专辑的艺术家信息,你可以床架一个artists表,兌到albums表,像tracks那样。你无需修改现有的结?-只是增加它?/p>

有效性来自于在你的数据中没有明显的数据重复且没有大量的空z(I单元)的实施。这样MySQL在你的数据库表中既不存储多余的数据,也不比花额外的精力搜索大量空区域?/p>

如果你对关系数据库是新手Q规范化你的数据看v来有点奇怪,但在存储和检索数据时Q它使MySQL非常有效Qƈl予你扩展和伸羃你的应用却不必多ơ重构你的数据库的灵zL。尽可能早的花时间想清楚数据库设计,q考虑你的需求怎样随时间增长,前期q旉永远是值得的?/p>

复合索引

复合索引Q有时称l合索引Q是急于多个列的单一索引。MySQL在处理一条查询时每个表只使用一个烦引,q意味着如果你有多个l常出现在WHERE子句中的列,你可能要通过创徏一个复合烦引来加快q些查询?/p>

考虑下列表结构片断:

 CREATE TABLE people (
   last_name       VARCHAR(50) NOT NULL,
   first_name      VARCHAR(50) NOT NULL,
   favorite_color  VARCHAR(10) NOT NULL,
   .
   .
   .
);

  

如果你常常基于last_name和first_name查询表,你可以从last_name和first_name的复合烦引中LQ?/p>

INDEX last_first (last_name, first_name) 

׃MySQL构徏复合索引的方式,它可以用last_first索引来回{基于last_name本n或last_name与first_name两者的索引。这是因为如果列涉及复合索引的“最左前~”的形式QMySQL只使用一个复合烦引?/p>

所以如果一个复合烦引有多个列合成:

INDEX big_index (a, b, c, d, e, f, g, h, i) 

MySQL可以用它来回{基于a、或a和b、或a和b和c、或a和b和c和d的查询。但它不能用big_index处理Ze、或c和f、或g和i的查询,因ؓq些序列没有一个是从烦引的最左边开始的?/p>

复合索引被用于加快某些复杂查询Q但你需要理解v局限,而且你永q应该进行一些测试,而不是简单地假设q样一个烦引将会有帮助?/p>


 
  
使用索引加快查询

当MySQL试图回达一条查询时Q它查看有关你的数据的各U统计,q决定如何以最快的速度扑և你想要的数据。对于前节的查询,MySQL读取albums表的所有titlesq把它们与“Billboard Top Hits --1984”进行比较看是否匚w。它一旦找C个匹配还不能停止Q因为有相同曲目的专辑不止一个(如你可以?2张CD标有“Greatest Hits”)Q结果MySQL必须d表中的每一行。这常称为“全表扫描”且可以避免?/p>

你应该避免全表扫描,因ؓQ?/p>

CPU开销Q如果你没有很多专辑Q检查所有这些标题的处理相对快些。但如果你需要在你的数据库中存储很多专辑呢?你有的专辑越多,q旉长。在专辑数量或检查它们所q旉旉存在一U线性关pR?i> 
q发性:在MySQL正在从表中读取数据时Q它锁定表得没有其他h可以写入Q但可以d。当MySQL更新或删除表中的行时Q它锁定表得没有其他h可以从它d?i> 
盘开销Q在一个大数据表上Q一ơ全表扫描将消耗大量磁盘I/O。这可能明显地减慢你的数据库服务?i> -- 特别是如果你的服务器是较慢的IDE驱动器?i> 
最好是让全表扫描将到最?i> -- 特别是你的应用需要以规模或用h伸羃。MySQL最新版实有几个ƈ发性方面的改善QBDB、InnoDB和Gemini表类型)?/p>

在这里烦引可以帮助你Q简单地放一个,一个烦引允许MySQL很快地确定Q何给定值如“Billboard Top Hits -- 1984”是否将匚w表中的Q何行?/p>

怎样做到的呢Q当你告诉MySQL索引一个特定列Ӟ它在q后创徏另一个数据结构(索引Qƈ用它存储关于被烦引列中的值的某些额外信息Q被索引的值常UCؓ健码Q。这是一U简化,MySQL所有键码存储在一个树状数据结构中。该数据l构允许MySQL非常快速地扑ֈ特定键码?/p>

当MySQL发现列上有一个烦引,它将使用索引而不是执行一个全表扫描。这节省了CPU旉Q不必读取所有可能的|和磁盘I/OQ而且它改善了q发性,因ؓMySQL只锁定表_长的旉来获得所需的行Q基于它在烦引中找什么)。当你在表中有大量的数据Q最l的改善可能非常明显?/p>

对图3的albums表的CREATE TABLE语句的改q:

?

CREATE TABLE albums (
    id        INTEGER      NOT NULL AUTO_INCREMENT PRIMARY KEY,
    title     VARCHAR(80)NOT NULL,
    
    INDEX title_idx (title)
);

 

正如你所见的Q语句只是简单地在定义后增加了一个INDEX行告诉MySQL在albums表中的title列上创徏名ؓtitle_idx的烦引。你可以l一个表增加多个索引Q就像你可在表中有多个列一栗单个烦引也可以有多个列合成?/p>

要给现有的表加上一个烦引而不是重Q你可以用ALTER TABLE命oQ?/p>

ALTER TABLE albums ADD INDEX title_idx (title)  

查询处理

如果你的查询复杂QMySQL用于_定如何获取数据的原则可能变得难于理解。幸q的是,有几个一般原则和一条命令允怽获得正在做什么的更好的理解。首先,原则是:

如果MySQL定了简单地扫描全表更快些,则它L不使用索引。一般地Q如果一个烦引告诉MySQL讉K表中大概30%的行Q它攑ּ索引q简单地执行全表扫描?i> 
如果多烦引可以用来满x询,MySQL用最严格的一?i> -- 卛_致最的行被提取的那个?i> 
如果你正在选择的列是一个烦引的所有部分,MySQL可以直接从烦引中d锁需的数据,l不接触Q或锁定Q表本n?i> 
当联l几个表ӞMySQL首先从可能q回最行的表中读取数据。你指定表的ơ序可能与MySQL使用它们的次序不同,q也影响到最l返回给你的行的ơ序Q所以如果你需要行以特定的ơ序出现Q要保证在你的查询中使用一个ORDER子句?i> 
已经说了很多了,重要的是认识到MySQL所做的一些决{实际上是基于猜,像人类q行大量猜测一P偶尔也会出错?i> 

如果你怀疑已l发生或只是想理解MySQL怎样处理一条查询,你可以用EXPLAIN命o。简单地在你的查询前面加上EXPLAINq个字,q要求MySQL执行它,MySQL不执行查询,相反报告有助于查询的候选烦引列表和所知道的有兛_们的一切?/p>

EXPLAIN输出的完整讨论参见MySQL参考手册?br /> 


不要q分使用索引

已经知道索引使查询更快,你可能們֐于烦引你表中的每个列。但是得益于索引的性能提高是有代h的,在表中每ơ执行INSERT、UPDATE、REPLACE或DELETEQMySQL不得不更新表上的每个索引以反映变化?/p>

那么你如何确定何旉用它们呢Q最常见的答案是“看情况”。它依赖你运行的查询cd和你q行它们的频度,它依赖于你的数据Q它依赖于你的期望和需求。你得到了答?i> -- 它依赖于很多事情?/p>

在列上有索引的理由是MySQL~窄其搜索范围以便尽可能会的匚w行(且避免全表扫描)。你可以认ؓ索引是对列中的每个唯一值只包含一V在索引中,MySQL必须考虑M重复|q些重复值稍微降低效率和索引的用途?/p>

所以在索引一个列之前Q考虑数据重复的百分比Q如果该癑ֈ比太高,你可能觉察不到用索引带来的Q何性能改善?/p>

要以更简明的术语描述Q它清楚地知道在albums表中索引曲目字段Q因为有可能有大量不同的|而且重复非常。但如果在albums表中有一个分cdQ烦引它则可能hg大,一般的CD攉包含多少不同的类型呢Q将会有很多重复的类型倹{?/p>

另一件要考虑的事情是你的查询可能使用的频度。MySQL只能对出现在一条查询种的WHERE子句中的特定列用烦引,试图回答查询Q?/p>

SELECT * FROM albums WHERE id = 500   

MySQL不能使用在title上的查询Q该查询要求MySQLZ其id查找记录而不是其title?i> 

如果你很用查询中WHERE子句中的一个列Q它可能不值得索引该列。可能在极少的情况下容h全表扫描比要求MySQL在每ơ修Ҏ保持索引更新M上更有效些?

有疑问时Q进行测试。你总能q行某些到烦引或不带索引的基准测试看哪一个更快,只要试图让你的基准测试逼真些。如果你的查询有20%是UPDATEQ?0%是SLEECTQ肯定你的基准测试能发映出来Q详见MySQL参考手册?/p>

使用REPLACE查询

有可能你惛_表中插入一条记录,除非它已l存在。如果记录已l存在,你想UPDATE它。不是重写代码中做这件事的逻辑Qƈ需q行多个查询Q而是MySQL使用REPLACE来做此项工作?/p>

如果id?的专辑假定有曲目“Shaking the Tree”,你可以这样写查询Q?/p>

REPLACE INTO albums valueS (6, 'Shaking the Tree')   

重要的是理解REPLACE如何定一条记录是否在表中存在。MySQL在表上使用PRIMARY KEY或UNIQUE KEY来执行检查,如果都不存在QREPLACE效果上变成了INSERT?/p>

使用临时?/p>

当工作在非常大的表上Ӟ你可能偶需要运行很多查询获得一个大量数据的的子集Q不是对整个表运行这些查询,而是让MySQL每次扑և所需的少数记录,记录选择C个时表可能更快些,然后多这些表q行查询?/p>

创徏临时表很ҎQ给正常的CREATE TABLE语句加上TEMPORARY关键字:

CREATE TEMPORARY TABLE tmp_table (
   name    VARCHAR(10) NOT NULL,
   value   INTEGER     NOT NULL
)

临时表将在你q接MySQL期间存在。当你断开ӞMySQL自动删除表q放所用的I间。当然你可以在仍然连接的时候删除表q攄间?/p>

DROP TABLE tmp_table   

如果在你创徏名ؓtmp_table临时表时名ؓtmp_table的表在数据库中已l存在,临时表将有必要屏蔽(隐藏Q非临时表tmp_table?/p>

如果你声明时表是一个HEAP表,MySQL也允怽指定在内存中创徏它:

 CREATE TEMPORARY TABLE tmp_table (
   name    VARCHAR(10) NOT NULL,
   value   INTEGER     NOT NULL
) TYPE = HEAP
  

因ؓHEAP表存储在内存中,你对它运行的查询可能比磁盘上的时表快些。然而,HEAP表与一般的表有些不同,且有自n的限制。详见MySQL参考手册?/p>

正如前面的徏议,你应该测试时表看看它们是否真的比对大量数据库运行查询快。如果数据很好地索引Q时表可能一点不快?/p>

临时表在MySQL 3.23.0和更新版才有?/p>

只用最新版的MySQL

2001q一月中旬,MySQL 3.23宣布E_。除了后很多新功能外Q它也比3.22pd更快和更具׾~性?/p>

MySQL的更新版不断推出。如果你控制着你的MySQL服务器,最好是试保持版本相对最新。除了有最新功能和错误修正Q你常常会看到较新的MySQL发行有明昄性能提高?/p>

其他资源

除了阅读MySQL手册Q你也可以咨询:

你的DBAQ如果你在一个共享服务器上用MySQLQ某个h被指定ؓ数据库管理员QDBAQ,q是一个好Z。如果你的DBA非常熟悉MySQLQ它可能可以在分析和优化你的表结构和查询上帮你一下?i> 
MySQL用户邮g列表Q有非常z跃的邮件列表,在其中MySQL用户l常彼此L帮助。新手和老手愿意分n其知识ƈ彼此帮助解决共同的问题。实际上Q有些MySQL开发团队成员很好地监视着邮g列表?i>  
MySQL书籍Q不要与MySQL参考手册؜淆,Paul DuBois写了一本极好的书名为《MySQL》的书(有中文译本)?



~程之道 2006-04-04 14:10 发表评论
]]>
ഺþ| þþþ㽶Ƶ| þþþþþþþþþþþ| ˾þô߽ۺվ| ѾþþƷ99reѾy| ݺɫþþۺƵպ | Ʒһþ㽶߿| 99þþƷ鶹| ƷŮٸaѾþ| ŷ޹׾þþþþþ| ޾Ʒþþþþ| ݺݾþۺ˲| ɫþþۺ| Ʒ91þþþþþa| 69Ʒþþþվ| һþaþþƷۺҹҹ | ޾ƷþþþĻ| ˾þô߽AV| þAٸ۲ӰԺ| þۺϸþúݺ97ɫ| ŷþþþþҹƷ| þþƷavӰԺ| һƷþ| ޾ƷþþþþͼƬ| þùƷһ| þ99ƷСѼ| þۺ³³| ޹ƷȾþ| Ʒݾþþþ| ޾ƷþþþþҲ | ŷ޾þav| þþþ޾ƷĻ| Ӱһþҹײ | þAVһ| þùһ| Ʒþþþþø69| AVպAVþþ| ˾þô߽ۺAv| þþƷAVһ| ޹˾þþƷ99| ĻƷѾþ|