还剩56页未读,继续阅读
本资源只提供10页预览,全部文档请下载后查看!喜欢就下载吧,查找使用更方便
文本内容:
Java实现单链表链表中的节点key代表节点的值,next是指向下一个节点的指针package02/***单链表节点*@authorsd*/08publicclassNode_Single{09publicStringkey;//节点的值11publicNode_Singlenext;//指向下一个的指针12publicNode_SingleStringkey{//初始化head14this.key=key;15this.next=null;16}17publicNode_SingleStringkeyNode_Singlenext{18this.key=key;19this.next=next;20}21publicStringgetKey{22returnkey;23}24publicvoidsetKeyStringkey{26this.key=key;27}28publicNode_SinglegetNext{30returnnext;31}32publicvoidsetNextNode_Singlenext{34this.next=next;35}36@Override37publicStringtoString{38returnNode_Single[key=+key+next=+next+];39}
2. [代码]简单实现的单链表链表的遍历,增加,删除 package/***单链表*@authorsd**/publicclassSingleList{privateNode_Singlehead=null;//头节点privateNode_Singletail=null;//尾节点空节点相当于哨兵元素/***初始化一个链表(设置head)*@paramkey*/publicvoidinitListNode_Singlenode{head=node;head.next=tail;}/***添加一个元素*@paramnode*/publicvoidaddTolistNode_Singlenode{ifhead==null{initListnode;}else{Node_Singletmp=head;head=node;node.next=tmp;}}/***遍历链表,删除某一个节点*@paramnode*@parammyList*/publicvoiddeleteNodeNode_SinglenodeSingleListmyList{ifmyList==null{return;}Node_Singletmp=null;fortmp=myList.getHead;tmp!=null;tmp=tmp.next{ifif}else{tmp.next=null;}}}}publicvoidprintListSingleListmyList{Node_Singletmp=null;fortmp=myList.getHead;tmp!=null;tmp=tmp.next{tmp.getKey;}}publicNode_SinglegetHead{returnhead;}publicvoidsetHeadNode_Singlehead{this.head=head;}publicNode_SinglegetTail{returntail;}publicvoidsetTailNode_Singletail{this.tail=tail;}publicstaticvoidmainString[]args{SingleListmyList=newSingleList;Node_Singlenode_1=newNode_Single1;Node_Singlenode_2=newNode_Single2;Node_Singlenode_3=newNode_Single3;Node_Singlenode_4=newNode_Single4;Node_Singlenode_5=newNode_Single5;Node_Singlenode_6=newNode_Single6;Node_Singlenode_7=newNode_Single7;myList.addTolistnode_1;myList.addTolistnode_2;myList.addTolistnode_3;myList.addTolistnode_4;myList.addTolistnode_5;myList.addTolistnode_6;myList.addTolistnode_7;myList.deleteNodenode_3myList;myList.printListmyList;}}另外的实现java实现范型单、双结点,单双列表 2008-10-2017:51:01转载▼//×××××××单结点的定义××××××××××× publicclassMyNodeT{ Tdata; MyNodenext; //MyNodenode; //默认构造方法 //MyNode{ // data=0; // } //构造方法 MyNodeTnode {this.data=node;} //重载toString方法,方便输出 publicStringtoString{ returnString.valueOfdata; } publicstaticvoidmainString[]args{ MyNodeStringnode1=newMyNodeString35; MyNodeStringnode2=newMyNodeString66; }} //×××××××××双结点的定义××××××××××××××××××××classMyDNodeTextendsMyNode{ //MyDNodenode; Tpre; //qian Tnext; //hou //Tdata; MyDNodeTdata { superdata; this.pre=null; } MyDNodeMyNodenode { supernode; this.pre=null; } publicStringtoString{ returnString.valueOfdata; } publicstaticvoidmainString[]args{ MyDNodeStringn=newMyDNodeString35; } }//%%%%%%%%%%%%单链表的实现%%%%%%%%%%%%%%%%%%%%%%%publicclassMyListT{ publicMyNodehead; publicTnode; publicintlength; MyList{ head=null; length=0; } MyListTn{ this.node=n; length=1; } //getlengthoflist publicintgetLength{ returnlength; } publicStringtoString{//输出的格式 Strings=; MyNodetempNode=head; forinti=1;i=length;i++{ s=s+getNodei+-; tempNode=tempNode.next; } returns; } //将节点node添加到单链表末尾 voidappendMyNodenode{ ifnode==null{ return; } ifhead==null{ head=node; }else{ getNodelength.next=node; } length++; } //根据参数返回单链表的第pos个节点 MyNodegetNodeintpos{ iflengthpos||pos1{ returnnull; } MyNodetempNode=head; forinti=1;ipos;i++{ tempNode=tempNode.next; } returntempNode; } //刪除 MyNodedelNodeintpos{ ifpos1||poslength{ returnnull; } MyNodetempnode=getNodepos;//獲得要刪除的結點 ifpos==1{//headnode head=getNode
1.next;//直接刪除頭指針 } else{ getNodepos-
1.next=tempnode.next; // tepnode.pre=getNodepos=
1.pre; } tempnode.next=null; length-=1; returntempnode; } MyNodeinsertNodeintpos{ MyNodee=newMyNode8; ifpos1||poslength{ returnnull; } MyNodenewnode=getNodepos; ifpos==1{//headnode head=getNode
1.next;//直接插入頭指針 } else{ //getNodepos-
1.next=newnode.next; //e.next=newnode; //getNodepos.next=e; e.next=getNodepos.next; getNodepos.next=e; } //newnode.next=null; length+=1; returnnewnode; } //合并两个单链表,将第二个单链表连接到第一个单链表末尾; staticvoidjoinMyListml_aMyListml_b{ ifml_a.length==0{ ml_a=ml_b; return; } ml_a.getNodeml_a.length.next=ml_b.getNode1; ml_a.length+=ml_b.length; } //翻转一个单链表; voidconvert{ iflength2{ return; } MyNodetemp=getNodelength; MyNodehead2=temp; forinti=length-1;i0;i--{ temp.next=getNodei; temp=temp.next; } temp.next=null; head=head2; } //复制一个单链表 voidcopyList{ } //判断单链表是否相等 booleanequalsMyListml{ returnfalse; } publicstaticvoidmainString[]args{ MyListMyNodeml=newMyListMyNode; MyListMyNodem2=newMyListMyNode; //MyListStringee=newMyListString99; MyNode[]nodes=newMyNode
[5]; forinti=0;inodes.length;i++{ //wrong:nodes[i].data=i*10; nodes[i]=newMyNodei*5; m
2.appendnodes[i]; } MyNoden=newMyNode1; MyNoden1=newMyNode21; MyNoden2=newMyNode31; ml.appendn;//将节点node添加到单链表末尾 ml.appendn1;//将节点node添加到单链表末尾 ml.appendn2; 列表一; 列表二;列表一翻转后为; //ml.convert; 列表二翻转后为; m
2.convert; 合并后的列表为; MyList.joinmlm2; ml.delNode3;删除第三个元素后的列表为;插入第三个元素后的列表为; ml.insertNode2; }}////··············双链表的实现···················· classMyDlist2TextendsMyList{ Tpre; //---------构造函数 MyDlist2{ head=null; pre=null; length=0; } MyDlist2Tn {//head=n; pre=n; length=1;} MyDNodedellintpos{//删除列表结点 ifpos1||poslength{ returnnull; } MyDNodetempnode=MyDNodegetNodpos; ifpos==1{//删除headnode getNodpos+
1.pre=null; } else{ //如果删除的不是头结点 getNodpos-
1.next=tempnode.next; getNodpos+
1.pre=tempnode.pre; } length-=1; returntempnode; } MyDNodegetNodintpos{ iflengthpos||pos1{ returnnull; } MyDNodetempNode=MyDNodehead; forinti=1;i=pos;i++{ tempNode=MyDNodetempNode.next; //tempNode.pre=getNodpos-1; } returntempNode; } MyDNodeinserlistintposMyDNodedate{//插入列表结点 ifpos1||poslength{ returnnull; } //MyDNodenewnode=MyDNodegetNod2; ifpos==1{//headnode getNod
1.next=null; } else{ //如果插入的不是头结点 qiancha getNodpos-
1.next=date; getNodpos.pre=date; date.pre=getNodpos-1; date.next=getNodpos; } //newnode.next=null; length+=1; returndate; } publicstaticvoidmainString[]args{ MyDlist2MyDNodeaa=newMyDlist2MyDNode; MyDlist2MyDNodecc=newMyDlist2MyDNode; MyDNodebb=newMyDNode8; MyDNode[]nodes=newMyDNode
[5]; forinti=0;inodes.length;i++{ nodes[i]=newMyDNodei*10; aa.appendnodes[i]; } MyDNode[]www=newMyDNode
[4]; forinti=0;iwww.length;i++{ www[i]=newMyDNodei*3; cc.appendwww[i]; } +cc; cc.convert; +cc; +aa; aa.convert; +aa; //aa.dell2; +aa; aa.inserlist3bb; insert: +aa; //MyDlist
2.joinaacc; +aa; 几种经典算法排序//插入排序:packageimport/***@authortreeroot*@since2006-2-2*@version
1.0*/publicclassInsertSortimplementsSortUtil.Sort{/**non-Javadocsortint[]*/publicvoidsortint[]data{inttemp;forinti=1;idata.length;i++{forintj=i;j0data[j]data[j-1];j--{SortUtil.swapdatajj-1;}}}}//冒泡排序:forvari=0;iarr.length;i++{forvarj=i+1;j=arr.length-1;j++{ifevalarr[i]evalarr[j]{temp=arr[i];arr[i]=arr[j];arr[j]=temp;}}}packageimport/***@authortreeroot*@since2006-2-2*@version
1.0*/publicclassBubbleSortimplementsSortUtil.Sort{/**non-Javadocsortint[]*/publicvoidsortint[]data{inttemp;forinti=0;idata.length;i++{forintj=data.length-1;ji;j--{ifdata[j]data[j-1]{SortUtil.swapdatajj-1;}}}}}//选择排序:packageimport/***@authortreeroot*@since2006-2-2*@version
1.0*/publicclassSelectionSortimplementsSortUtil.Sort{/***non-Javadoc*sortint[]*/publicvoidsortint[]data{inttemp;forinti=0;idata.length;i++{intlowIndex=i;forintj=data.length-1;ji;j--{ifdata[j]data[lowIndex]{lowIndex=j;}}SortUtil.swapdatailowIndex;}}}//Shell排序:packageimport/***@authortreeroot*@since2006-2-2*@version
1.0*/publicclassShellSortimplementsSortUtil.Sort{/**non-Javadocsortint[]*/publicvoidsortint[]data{forinti=data.length/2;i2;i/=2{forintj=0;ji;j++{insertSortdataji;}}insertSortdata01;}/***@paramdata*@paramj*@parami*/privatevoidinsertSortint[]dataintstartintinc{inttemp;forinti=start+inc;idata.length;i+=inc{forintj=i;j=incdata[j]data[j-inc];j-=inc{SortUtil.swapdatajj-inc;}}}}//快速排序:packageimport/***@authortreeroot*@since2006-2-2*@version
1.0*/publicclassQuickSortimplementsSortUtil.Sort{/**non-Javadocsortint[]*/publicvoidsortint[]data{quickSortdata0data.length-1;}privatevoidquickSortint[]dataintiintj{intpivotIndex=i+j/2;//swapSortUtil.swapdatapivotIndexj;intk=partitiondatai-1jdata[j];SortUtil.swapdatakj;ifk-i1quickSortdataik-1;ifj-k1quickSortdatak+1j;}/***@paramdata*@parami*@paramj*@return*/privateintpartitionint[]dataintlintrintpivot{do{whiledata[++l]pivot;whiler!=0data[--r]pivot;SortUtil.swapdatalr;}whilelr;SortUtil.swapdatalr;returnl;}}//改进后的快速排序:packageimport/***@authortreeroot*@since2006-2-2*@version
1.0*/publicclassImprovedQuickSortimplementsSortUtil.Sort{privatestaticintMAX_STACK_SIZE=4096;privatestaticintTHRESHOLD=10;/**non-Javadocsortint[]*/publicvoidsortint[]data{int[]stack=newint[MAX_STACK_SIZE];inttop=-1;intpivot;intpivotIndexlr;stack[++top]=0;stack[++top]=data.length-1;whiletop0{intj=stack[top--];inti=stack[top--];pivotIndex=i+j/2;pivot=data[pivotIndex];SortUtil.swapdatapivotIndexj;//partitionl=i-1;r=j;do{whiledata[++l]pivot;whiler!=0data[--r]pivot;SortUtil.swapdatalr;}whilelr;SortUtil.swapdatalr;SortUtil.swapdatalj;ifl-iTHRESHOLD{stack[++top]=i;stack[++top]=l-1;}ifj-lTHRESHOLD{stack[++top]=l+1;stack[++top]=j;}}//newInsertSort.sortdata;insertSortdata;}/***@paramdata*/privatevoidinsertSortint[]data{inttemp;forinti=1;idata.length;i++{forintj=i;j0data[j]data[j-1];j--{SortUtil.swapdatajj-1;}}}}//归并排序:packageimport/***@authortreeroot*@since2006-2-2*@version
1.0*/publicclassMergeSortimplementsSortUtil.Sort{/**non-Javadocsortint[]*/publicvoidsortint[]data{int[]temp=newint[data.length];mergeSortdatatemp0data.length-1;}privatevoidmergeSortint[]dataint[]tempintlintr{intmid=l+r/2;ifl==rreturn;mergeSortdatatemplmid;mergeSortdatatempmid+1r;forinti=l;i=r;i++{temp[i]=data[i];}inti1=l;inti2=mid+1;forintcur=l;cur=r;cur++{ifi1==mid+1data[cur]=temp[i2++];elseifi2rdata[cur]=temp[i1++];elseiftemp[i1]temp[i2]data[cur]=temp[i1++];elsedata[cur]=temp[i2++];}}}//改进后的归并排序:packageimport/***@authortreeroot*@since2006-2-2*@version
1.0*/publicclassImprovedMergeSortimplementsSortUtil.Sort{privatestaticfinalintTHRESHOLD=10;/***non-Javadoc*sortint[]*/publicvoidsortint[]data{int[]temp=newint[data.length];mergeSortdatatemp0data.length-1;}privatevoidmergeSortint[]dataint[]tempintlintr{intijk;intmid=l+r/2;ifl==rreturn;ifmid-l=THRESHOLDmergeSortdatatemplmid;elseinsertSortdatalmid-l+1;ifr-midTHRESHOLDmergeSortdatatempmid+1r;elseinsertSortdatamid+1r-mid;fori=l;i=mid;i++{temp[i]=data[i];}forj=1;j=r-mid;j++{temp[r-j+1]=data[j+mid];}inta=temp[l];intb=temp[r];fori=lj=rk=l;k=r;k++{ifab{data[k]=temp[i++];a=temp[i];}else{data[k]=temp[j--];b=temp[j];}}}/***@paramdata*@paraml*@parami*/privatevoidinsertSortint[]dataintstartintlen{forinti=start+1;istart+len;i++{forintj=i;jstartdata[j]data[j-1];j--{SortUtil.swapdatajj-1;}}}}//堆排序:packageimport/***@authortreeroot*@since2006-2-2*@version
1.0*/publicclassHeapSortimplementsSortUtil.Sort{/**non-Javadocsortint[]*/publicvoidsortint[]data{MaxHeaph=newMaxHeap;h.initdata;forinti=0;idata.length;i++h.remove;System.arraycopyh.queue1data0data.length;}privatestaticclassMaxHeap{voidinitint[]data{this.queue=newint[data.length+1];forinti=0;idata.length;i++{queue[++size]=data[i];fixUpsize;}}privateintsize=0;privateint[]queue;publicintget{returnqueue
[1];}publicvoidremove{SortUtil.swapqueue1size--;fixDown1;}//fixdownprivatevoidfixDownintk{intj;whilej=k1=size{ifjsizequeue[j]queue[j+1]j++;ifqueue[k]queue[j]//不用交换break;SortUtil.swapqueuejk;k=j;}}privatevoidfixUpintk{whilek1{intj=k1;ifqueue[j]queue[k]break;SortUtil.swapqueuejk;k=j;}}}}//SortUtil:packageimportimportimportimportimportimportimportimportimport/***@authortreeroot*@since2006-2-2*@version
1.0*/publicclassSortUtil{publicfinalstaticintINSERT=1;publicfinalstaticintBUBBLE=2;publicfinalstaticintSELECTION=3;publicfinalstaticintSHELL=4;publicfinalstaticintQUICK=5;publicfinalstaticintIMPROVED_QUICK=6;publicfinalstaticintMERGE=7;publicfinalstaticintIMPROVED_MERGE=8;publicfinalstaticintHEAP=9;publicstaticvoidsortint[]data{sortdataIMPROVED_QUICK;}privatestaticString[]name={insertbubbleselectionshellquickimproved_quickmergeimproved_mergeheap};privatestaticSort[]impl=newSort[]{newInsertSortnewBubbleSortnewSelectionSortnewShellSortnewQuickSortnewImprovedQuickSortnewMergeSortnewImprovedMergeSortnewHeapSort};publicstaticStringtoStringintalgorithm{returnname[algorithm-1];}publicstaticvoidsortint[]dataintalgorithm{impl[algorithm-1].sortdata;}publicstaticinterfaceSort{publicvoidsortint[]data;}publicstaticvoidswapint[]dataintiintj{inttemp=data[i];data[i]=data[j];data[j]=temp;}}拉钩面试题publicclasslagou{publicstaticfinalStringOUT1=Fizz;publicstaticfinalStringOUT2=Buzz;publicstaticfinalStringOUT3=Whizz;publicstaticvoidmainString[]args{try{BufferedReaderreader=newBufferedReadernewInputStreamReaderSystem.in;intinput1=Integer.parseIntreader.readLine;intinput2=Integer.parseIntreader.readLine;intinput3=Integer.parseIntreader.readLine;inti=1;whilei=100{Stringresult=analyzeiinput1input2input3;result.length==0i:result;\n;i++;}}catchIOExceptione{e.printStackTrace;}}另一种解决方法packagepublicclassFizzBuzzWhizz{privateintnum[];//传入的不同的特殊数privateintamount;//共有多少名学生privateStringsayWhat[];//规则是什么?规则是根据方规则的不同调用不同的方法//由于规则只包含个位数的,就不弄两位数了/**这里可以弄个map什么的,没搞,先用数组顶替*/publicFizzBuzzWhizz{}publicFizzBuzzWhizzint[]numintamountStringsayWhat[]{this.num=num;this.amount=amount;this.sayWhat=sayWhat;}publicvoidprintAllAmount{forinti=1;i=amount;i++{rule5i;}}publicvoidrule5intsequenceAmount{/**在这里如果范围超过100100010000,甚至更多的时候,到时候*可以改成循环自动调用因为“长”的都一样*/ifsequenceAmount0sequenceAmount10{//每一个中都是两种情况ifsequenceAmount==num
[0]{sequenceAmount++sayWhat
[0];}else{sequenceAmount+;forinti=0;inum.length;i++{rule3sequenceAmountnum[i]i;//为了格式漂亮ifi==num.length-1{;}}}}elseifsequenceAmount9sequenceAmount100{/**这里可以写一种方法判断一个数中包含了另外的数字*这里是可以提取出来的,以后有时间提取*/inta=sequenceAmount/10;//英文忘记了,没改intb=sequenceAmount%10;ifa==num
[0]||b==num
[0]{sequenceAmount++sayWhat
[0];}else{sequenceAmount+;forinti=0;inum.length;i++{rule3sequenceAmountnum[i]i;//为了格式漂亮ifi==num.length-1{;}}}}else{//这里简单写了,和别的是一样的,比如判断除数是否为0,,等等,//因为是100if1==num
[0]{sequenceAmount++sayWhat
[0];}else{sequenceAmount+;forinti=0;inum.length;i++{rule3sequenceAmountnum[i]i;//为了格式漂亮ifi==num.length-1{;}}}}}publicvoidrule3intsequenceAmountintnumDevidedinti{ifsequenceAmount%numDevided==0{sayWhat[i];}}}package/***FizzBuzzWhizz你是一名体育老师,在某次课距离下课还有五分钟时,你决定搞一个游戏此时有100名学生在上课游戏的规则是
1.你首先说出三个不同的特殊数,要求必须是个位数,比如
3、
5、
72.让所有学生拍成一队,然后按顺序报数
3.学生报数时,如果所报数字是第一个特殊数
(3)的倍数,那么不能说该数字,而要说Fizz;如果所报数字是第二个特殊数
(5)的倍数,那么要说Buzz;如果所报数字是第三个特殊数
(7)的倍数,那么要说Whizz
4.学生报数时,如果所报数字同时是两个特殊数的倍数情况下,也要特殊处理,比如第一个特殊数和第二个特殊数的倍数,那么不能说该数字,而是要说FizzBuzz以此类推如果同时是三个特殊数的倍数,那么要说FizzBuzzWhizz
5.学生报数时,如果所报数字包含了第一个特殊数,那么也不能说该数字,而是要说相应的单词,比如本例中第一个特殊数是3,那么要报13的同学应该说Fizz如果数字中包含了第一个特殊数,那么忽略规则3和规则4,比如要报35的同学只报Fizz,不报BuzzWhizz*@authorzhao**/publicclassFizzBuzzWhizzTest{publicstaticvoidmainString[]args{/**赋值,测试*/intnum[];//传入的不同的特殊数intamount;//共有多少名学生StringsayWhat[];num=newint
[3];sayWhat=newString
[3];num
[0]=3;num
[1]=5;num
[2]=7;sayWhat
[0]=Fizz;sayWhat
[1]=Buzz;sayWhat
[2]=Whizz;amount=100;FizzBuzzWhizzfbw=newFizzBuzzWhizznumamountsayWhat;fbw.printAllAmount;}}MySQl面试题
1.如何写出高质量、高性能的MySQL查询答案下面就某些SQL语句的where子句编写中需要注意的问题作详细介绍在这些where子句中,即使某些列存在索引,但是由于编写了劣质的SQL,系统在运行该SQL语句时也不能使用该索引,而同样使用全表扫描,这就造成了响应速度的极大降低
1.ISNULL与ISNOTNULL不能用null作索引,任何包含null值的列都将不会被包含在索引中即使索引有多列这样的情况下,只要这些列中有一列含有null,该列就会从索引中排除也就是说如果某列存在空值,即使对该列建索引也不会提高性能任何在where子句中使用isnull或isnotnull的语句优化器是不允许使用索引的
2.联接列对于有联接的列,即使最后的联接值为一个静态值,优化器是不会使用索引的我们一起来看一个例子,假定有一个职工表(employee),对于一个职工的姓和名分成两列存放(FIRST_NAME和LAST_NAME),现在要查询一个叫比尔.克林顿(BillCliton)的职工下面是一个采用联接查询的SQL语句,select*fromemploysswherefirst_name||||last_name=BeillCliton上面这条语句完全可以查询出是否有BillCliton这个员工,但是这里需要注意,系统优化器对基于last_name创建的索引没有使用当采用下面这种SQL语句的编写,Oracle系统就可以采用基于last_name创建的索引Select*fromemployeewherefirst_name=Beillandlast_name=Cliton遇到下面这种情况又如何处理呢?如果一个变量(name)中存放着BillCliton这个员工的姓名,对于这种情况我们又如何避免全程遍历,使用索引呢?可以使用一个函数,将变量name中的姓和名分开就可以了,但是有一点需要注意,这个函数是不能作用在索引列上下面是SQL查询脚本select*fromemployeewherefirst_name=SUBSTRname1INSTRname-1andlast_name=SUBSTRnameINSTRname’+
13.带通配符(%)的like语句同样以上面的例子来看这种情况目前的需求是这样的,要求在职工表中查询名字中包含cliton的人可以采用如下的查询SQL语句select*fromemployeewherelast_namelike%cliton%这里由于通配符(%)在搜寻词首出现,所以Oracle系统不使用last_name的索引在很多情况下可能无法避免这种情况,但是一定要心中有底,通配符如此使用会降低查询速度然而当通配符出现在字符串其他位置时,优化器就能利用索引在下面的查询中索引得到了使用select*fromemployeewherelast_namelikec%
4.Orderby语句ORDERBY语句决定了Oracle如何将返回的查询结果排序Orderby语句对要排序的列没有什么特别的限制,也可以将函数加入列中(象联接或者附加等)任何在Orderby语句的非索引项或者有计算表达式都将降低查询速度仔细检查orderby语句以找出非索引项或者表达式,它们会降低性能解决这个问题的办法就是重写orderby语句以使用索引,也可以为所使用的列建立另外一个索引,同时应绝对避免在orderby子句中使用表达式
5.NOT我们在查询时经常在where子句使用一些逻辑表达式,如大于、小于、等于以及不等于等等,也可以使用and(与)、or(或)以及not(非)NOT可用来对任何逻辑运算符号取反下面是一个NOT子句的例子…wherenotstatus=’VALID’如果要使用NOT,则应在取反的短语前面加上括号,并在短语前面加上NOT运算符NOT运算符包含在另外一个逻辑运算符中,这就是不等于()运算符换句话说,即使不在查询where子句中显式地加入NOT词,NOT仍在运算符中,见下例…wherestatus’INVALID’再看下面这个例子select*fromemployeewheresalary3000;对这个查询,可以改写为不使用NOT select*fromemployeewheresalary3000orsalary3000;虽然这两种查询的结果一样,但是第二种查询方案会比第一种查询方案更快些第二种查询允许Oracle对salary列使用索引,而第一种查询则不能使用索引
6.IN和EXISTS有时候会将一列和一系列值相比较最简单的办法就是在where子句中使用子查询在where子句中可以使用两种格式的子查询第一种格式是使用IN操作符…wherecolumninselect*from…where…;第二种格式是使用EXIST操作符…whereexistsselect‘X’from…where…;我相信绝大多数人会使用第一种格式,因为它比较容易编写,而实际上第二种格式要远比第一种格式的效率高在Oracle中可以几乎将所有的IN操作符子查询改写为使用EXISTS的子查询第二种格式中,子查询以‘select‘X’开始运用EXISTS子句不管子查询从表中抽取什么数据它只查看where子句这样优化器就不必遍历整个表而仅根据索引就可完成工作(这里假定在where语句中使用的列存在索引)相对于IN子句来说,EXISTS使用相连子查询,构造起来要比IN子查询困难一些通过使用EXIST,Oracle系统会首先检查主查询,然后运行子查询直到它找到第一个匹配项,这就节省了时间Oracle系统在执行IN子查询时,首先执行子查询,并将获得的结果列表存放在在一个加了索引的临时表中在执行子查询之前,系统先将主查询挂起,待子查询执行完毕,存放在临时表中以后再执行主查询这也就是使用EXISTS比使用IN通常查询速度快的原因同时应尽可能使用NOTEXISTS来代替NOTIN,尽管二者都使用了NOT(不能使用索引而降低速度),NOTEXISTS要比NOTIN查询效率更高
2、几个MySql的面试题答案
3、简单叙述一下MYSQL的优化
1.数据库的设计尽量把数据库设计的更小的占磁盘空间.
1.尽可能使用更小的整数类型.mediumint就比int更合适.
2.尽可能的定义字段为notnull除非这个字段需要null.
3.如果没有用到变长字段的话比如varchar那就采用固定大小的纪录格式比如char.
4.表的主索引应该尽可能的短.这样的话每条纪录都有名字标志且更高效.
5.只创建确实需要的索引索引有利于检索记录,但是不利于快速保存记录如果总是要在表的组合字段上做搜索,那么就在这些字段上创建索引索引的第一部分必须是最常使用的字段.如果总是需要用到很多字段,首先就应该多复制这些字段,使索引更好的压缩
6.所有数据都得在保存到数据库前进行处理
7.所有字段都得有默认值
8.在某些情况下把一个频繁扫描的表分成两个速度会快好多在对动态格式表扫描以取得相关记录时,它可能使用更小的静态格式表的情况下更是如此
2.系统的用途
1.尽量使用长连接.
2.explain复杂的SQL语句
3.如果两个关联表要做比较话,做比较的字段必须类型和长度都一致.
4.LIMIT语句尽量要跟orderby或者distinct.这样可以避免做一次fulltablescan.
5.如果想要清空表的所有纪录建议用truncatetabletablename而不是deletefromtablename.
6.能使用STOREPROCEDURE或者USERFUNCTION的时候.
7.在一条insert语句中采用多重纪录插入格式.而且使用loaddatainfile来导入大量数据,这比单纯的indert快好多.
8.经常OPTIMIZETABLE来整理碎片.
9.还有就是date类型的数据如果频繁要做比较的话尽量保存在unsignedint类型比较快
3.系统的瓶颈
1.磁盘搜索.并行搜索把数据分开存放到多个磁盘中,这样能加快搜索时间.
2.磁盘读写IO可以从多个媒介中并行的读取数据
3.CPU周期数据存放在主内存中.这样就得增加CPU的个数来处理这些数据
4.内存带宽当CPU要将更多的数据存放到CPU的缓存中来的话内存的带宽就成了瓶颈.
4、MySQL面试题目集锦
1、MySQL取得当前时间的函数是,格式化日期的函数是
2、写出SQL语句的格式:插入,更新,删除表名UserNameTelContentDate张三大专毕业2006-10-11张三本科毕业2006-10-15张四021-55665566中专毕业2006-10-15a有一新记录小王高中毕业2007-05-06请用SQL语句新增至表中b请用sql语句把张三的时间更新成为当前系统时间c请写出删除名为张四的全部记录
3、请写出数据类型intcharvarchardatetimetext的意思;请问varchar和char有什么区别
4、MySQL自增类型通常为表ID字段必需将其设为字段
5、以下请用PHPMYADMIN完成一创建新闻发布系统,表名为message有如下字段id文章idtitle文章标题content文章内容category_id文章分类idhits点击量二同样上述新闻发布系统表comment记录用户回复内容,字段如下comment_id回复idid文章id,关联message表中的idcomment_content回复内容现通过查询数据库需要得到以下格式的文章标题列表并按照回复数量排序,回复最高的排在最前面文章id文章标题点击量回复数量用一个SQL语句完成上述查询,如果文章没有回复则回复数量显示为0三上述内容管理系统,表category保存分类信息,字段如下category_idint4notnullauto_increment;categroy_namevarchar40notnull;用户输入文章时,通过选择下拉菜单选定文章分类写出如何实现这个下拉菜单
5、如何提高Mysql的安全性
1.如果MYSQL客户端和服务器端的连接需要跨越并通过不可信任的网络,那么需要使用ssh隧道来加密该连接的通信
2.使用setpassword语句来修改用户的密码,先“mysql-uroot”登陆数据库系统,然后“mysqlupdatemysql.usersetpassword=password‘newpwd’”,最后执行“flushprivileges”就可以了
3.Mysql需要提防的攻击有,防偷听、篡改、回放、拒绝服务等,不涉及可用性和容错方面对所有的连接、查询、其他操作使用基于acl即访问控制列表的安全措施来完成也有一些对ssl连接的支持
4.设置除了root用户外的其他任何用户不允许访问mysql主数据库中的user表;加密后存放在user表中的加密后的用户密码一旦泄露,其他人可以随意用该用户名/密码相应的数据库;
5.使用grant和revoke语句来进行用户访问控制的工作;
6.不要使用明文密码,而是使用md5和sha1等单向的哈系函数来设置密码;
7.不要选用字典中的字来做密码;
8.采用防火墙可以去掉50%的外部危险,让数据库系统躲在防火墙后面工作,或放置在dmz区域中;
9.从因特网上用nmap来扫描3306端口,也可用telnetserver_host3306的方法测试,不允许从非信任网络中访问数据库服务器的3306号tcp端口,需要在防火墙或路由器上做设定;
10.为了防止被恶意传入非法参数,例如whereid=234,别人却输入whereid=234or1=1导致全部显示,所以在web的表单中使用”或”来用字符串,在动态url中加入%22代表双引号、%23代表井号、%27代表单引号;传递未检查过的值给mysql数据库是非常危险的;
11.在传递数据给mysql时检查一下大小;
12.应用程序需要连接到数据库应该使用一般的用户帐号,开放少数必要的权限给该用户;$page_devide$
13.在各编程接口cc++phpperljavajdbc等中使用特定‘逃脱字符’函数;在因特网上使用mysql数据库时一定少用传输明文的数据,而用ssl和ssh的加密方式数据来传输;
14.学会使用tcpdump和strings工具来查看传输数据的安全性,例如tcpdump-l-ieth0-w-srcordstport3306strings以普通用户来启动mysql数据库服务;
15.不使用到表的联结符号,选用的参数–skip-symbolic-links;
16.确信在mysql目录中只有启动数据库服务的用户才可以对文件有读和写的权限;
17.不许将process或super权限付给非管理用户,该mysqladminprocesslist可以列举出当前执行的查询文本;super权限可用于切断客户端连接、改变服务器运行参数状态、控制拷贝复制数据库的服务器;
18.file权限不付给管理员以外的用户,防止出现loaddata‘/etc/passwd’到表中再用select显示出来的问题;
19.如果不相信dns服务公司的服务,可以在主机名称允许表中只设置ip数字地址;
20.使用max_user_connections变量来使mysqld服务进程,对一个指定帐户限定连接数;
21.grant语句也支持资源控制选项;
22.启动mysqld服务进程的安全选项开关,–local-infile=0或1若是0则客户端程序就无法使用localloaddata了,赋权的一个例子grantinsertuseronmysql.userto‘user_name’@host_name’;若使用–skip-grant-tables系统将对任何用户的访问不做任何访问控制,但可以用mysqladminflush-privileges或mysqladminreload来开启访问控制;默认情况是showdatabases语句对所有用户开放,可以用–skip-show-databases来关闭掉
23.碰到error104528000accessdeniedforuser‘root’@localhost’usingpassword:no错误时,你需要重新设置密码,具体方法是:先用–skip-grant-tables参数启动mysqld,然后执行mysql-urootmysqlmysqlupdateusersetpassword=password‘newpassword’whereuser=’root’;mysqlflushprivileges;,最后重新启动mysql就可以了
6、介绍一下Mysql存储引擎存储引擎是什么?MySQL中的数据用各种不同的技术存储在文件或者内存中这些技术中的每一种技术都使用不同的存储机制、索引技巧、锁定水平并且最终提供广泛的不同的功能和能力通过选择不同的技术,你能够获得额外的速度或者功能,从而改善你的应用的整体功能例如,如果你在研究大量的临时数据,你也许需要使用内存存储引擎内存存储引擎能够在内存中存储所有的表格数据又或者,你也许需要一个支持事务处理的数据库以确保事务处理不成功时数据的回退能力这些不同的技术以及配套的相关功能在MySQL中被称作存储引擎也称作表类型MySQL默认配置了许多不同的存储引擎,可以预先设置或者在MySQL服务器中启用你可以选择适用于服务器、数据库和表格的存储引擎,以便在选择如何存储你的信息、如何检索这些信息以及你需要你的数据结合什么性能和功能的时候为你提供最大的灵活性选择如何存储和检索你的数据的这种灵活性是MySQL为什么如此受欢迎的主要原因其它数据库系统包括大多数商业选择仅支持一种类型的数据存储遗憾的是,其它类型的数据库解决方案采取的“一个尺码满足一切需求”的方式意味着你要么就牺牲一些性能,要么你就用几个小时甚至几天的时间详细调整你的数据库使用MySQL,我们仅需要修改我们使用的存储引擎就可以了在这篇文章中,我们不准备集中讨论不同的存储引擎的技术方面的问题尽管我们不可避免地要研究这些因素的某些方面,相反,我们将集中介绍这些不同的引擎分别最适应哪种需求和如何启用不同的存储引擎为了实现这个目的,在介绍每一个存储引擎的具体情况之前,我们必须要了解一些基本的问题如何确定有哪些存储引擎可用你可以在MySQL假设是MySQL服务器以上版本中使用显示引擎的命令得到一个可用引擎的列表mysqlshowengines;+------------+---------+----------------------------------------------------+|Engine|Support|Comment|+------------+---------+-----------------------------------------------------+|MyISAM|DEFAULT|DefaultengineasofMySQL
3.23withgreatperformance||HEAP|YES|AliasforMEMORY||MEMORY|YES|Hashbasedstoredinmemoryusefulfortemporarytables||MERGE|YES|CollectionofidenticalMyISAMtables||MRG_MYISAM|YES|AliasforMERGE||ISAM|NO|ObsoletestorageenginenowreplacedbyMyISAM||MRG_ISAM|NO|ObsoletestorageenginenowreplacedbyMERGE||InnoDB|YES|Supportstransactionsrow-levellockingandforeignkeys||INNOBASE|YES|AliasforINNODB||BDB|NO|Supportstransactionsandpage-levellocking||BERKELEYDB|NO|AliasforBDB||NDBCLUSTER|NO|Clusteredfault-tolerantmemory-basedtables||NDB|NO|AliasforNDBCLUSTER||EXAMPLE|NO|Examplestorageengine||ARCHIVE|NO|Archivestorageengine||CSV|NO|CSVstorageengine|+------------+---------+-------------------------------------------------------+16rowsinset
0.01sec 这个表格显示了可用的数据库引擎的全部名单以及在当前的数据库服务器中是否支持这些引擎对于以前版本,可以使用mysqlshowvariableslike“have_%”显示类似“have_%”的变量:mysqlshowvariableslikehave_%;+------------------+----------+|Variable_name|Value|+------------------+----------+|have_bdb|YES||have_crypt|YES||have_innodb|DISABLED||have_isam|YES||have_raid|YES||have_symlink|YES||have_openssl|YES||have_query_cache|YES|+------------------+----------+8rowsinset
0.01sec你可以通过修改设置脚本中的选项来设置在MySQL安装软件中可用的引擎如果你在使用一个预先包装好的MySQL二进制发布版软件,那么,这个软件就包含了常用的引擎然而,需要指出的是,如果你要使用某些不常用的引擎,特别是CSV、RCHIVE存档和BLACKHOLE黑洞引擎,你就需要手工重新编译MySQL源码使用一个指定的存储引擎你可以使用很多方法指定一个要使用的存储引擎最简单的方法是,如果你喜欢一种能满足你的大多数数据库需求的存储引擎,你可以在MySQL设置文件中设置一个默认的引擎类型(使用storage_engine选项)或者在启动数据库服务器时在命令行后面加上–default-storage-engine或–default-table-type选项更灵活的方式是在随MySQL服务器发布同时提供的MySQL客户端时指定使用的存储引擎最直接的方式是在创建表时指定存储引擎的类型,向下面这样: CREATETABLEmytableidinttitlechar20ENGINE=INNODB你还可以改变现有的表使用的存储引擎,用以下语句: ALTERTABLEmytableENGINE=MyISAM然而,你在以这种方式修改表格类型的时候需要非常仔细,因为对不支持同样的索引、字段类型或者表大小的一个类型进行修改可能使你丢失数据如果你指定一个在你的当前的数据库中不存在的一个存储引擎,那么就会创建一个MyISAM默认的类型的表各存储引擎之间的区别为了做出选择哪一个存储引擎的决定,我们首先需要考虑每一个存储引擎提供了哪些不同的核心功能这种功能使我们能够把不同的存储引擎区别开来我们一般把这些核心功能分为四类:支持的字段和数据类型、锁定类型、索引和处理一些引擎具有能过促使你做出决定的独特的功能,我们一会儿再仔细研究这些具体问题字段和数据类型虽然所有这些引擎都支持通用的数据类型,例如整型、实型和字符型等,但是,并不是所有的引擎都支持其它的字段类型,特别是BLOG(二进制大对象)或者TEXT文本类型其它引擎也许仅支持有限的字符宽度和数据大小这些局限性可能直接影响到你可以存储的数据,同时也可能会对你实施的搜索的类型或者你对那些信息创建的索引产生间接的影响这些区别能够影响你的应用程序的性能和功能,因为你必须要根据你要存储的数据类型选择对需要的存储引擎的功能做出决策锁定数据库引擎中的锁定功能决定了如何管理信息的访问和更新当数据库中的一个对象为信息更新锁定了,在更新完成之前,其它处理不能修改这个数据在某些情况下还不允许读这种数据锁定不仅影响许多不同的应用程序如何更新数据库中的信息,而且还影响对那个数据的查询这是因为查询可能要访问正在被修改或者更新的数据总的来说,这种延迟是很小的大多数锁定机制主要是为了防止多个处理更新同一个数据由于向数据中插入信息和更新信息这两种情况都需要锁定,你可以想象,多个应用程序使用同一个数据库可能会有很大的影响不同的存储引擎在不同的对象级别支持锁定,而且这些级别将影响可以同时访问的信息得到支持的级别有三种:表锁定、块锁定和行锁定支持最多的是表锁定,这种锁定是在MyISAM中提供的在数据更新时,它锁定了整个表这就防止了许多应用程序同时更新一个具体的表这对应用很多的多用户数据库有很大的影响,因为它延迟了更新的过程页级锁定使用BerkeleyDB引擎,并且根据上载的信息页8KB锁定数据当在数据库的很多地方进行更新的时候,这种锁定不会出现什么问题但是,由于增加几行信息就要锁定数据结构的最后8KB,当需要增加大量的行,也别是大量的小型数据,就会带来问题行级锁定提供了最佳的并行访问功能,一个表中只有一行数据被锁定这就意味着很多应用程序能够更新同一个表中的不同行的数据,而不会引起锁定的问题只有InnoDB存储引擎支持行级锁定建立索引建立索引在搜索和恢复数据库中的数据的时候能够显著提高性能不同的存储引擎提供不同的制作索引的技术有些技术也许会更适合你存储的数据类型有些存储引擎根本就不支持索引,其原因可能是它们使用基本表索引如MERGE引擎或者是因为数据存储的方式不允许索引例如FEDERATED或者BLACKHOLE引擎事务处理事务处理功能通过提供在向表中更新和插入信息期间的可靠性这种可靠性是通过如下方法实现的,它允许你更新表中的数据,但仅当应用的应用程序的所有相关操作完全完成后才接受你对表的更改例如,在会计处理中每一笔会计分录处理将包括对借方科目和贷方科目数据的更改,你需要要使用事务处理功能保证对借方科目和贷方科目的数据更改都顺利完成,才接受所做的修改如果任一项操作失败了,你都可以取消这个事务处理,这些修改就不存在了如果这个事务处理过程完成了,我们可以通过允许这个修改来确认这个操作
7、介绍一下如何优化Mysql语句性能
一、在编译时优化MySQL如果你从源代码分发安装MySQL,要注意,编译过程对以后的目标程序性能有重要的影响,不同的编译方式可能得到类似的目标文件,但性能可能相差很大,因此,在编译安装MySQL适应仔细根据你的应用类型选择最可能好的编译选项这种定制的MySQL可以为你的应用提供最佳性能技巧选用较好的编译器和较好的编译器选项,这样应用可提高性能10-30%(MySQL文档如是说)
1.
1、使用pgcc(PentiumGCC编译器该编译器()针对运行在奔腾处理器系统上的程序进行优化,用pgcc编译MySQL源代码,总体性能可提高10%当然如果你的服务器不是用奔腾处理器,就不必用它了,因为它是专为奔腾系统设计的
1.
2、仅使用你想使用的字符集编译MySQLMySQL目前提供多达24种不同的字符集,为全球用户以他们自己的语言插入或查看表中的数据却省情况下,MySQL安装所有者这些字符集,热然而,最好的选择是指选择一种你需要的如,禁止除Latin1字符集以外的所有其它字符集——————————————————————————–%./configure-with-extra-charsets=none[--other-configuration-options]——————————————————————————–
1.
3、将mysqld编译成静态执行文件将mysqld编译成静态执行文件而无需共享库也能获得更好的性能通过在配置时指定下列选项,可静态编译mysqld——————————————————————————–%./configure-with-mysqld-ldflags=-all-static[--other-configuration-options]——————————————————————————–
1.
4、配置样本下列配置命令常用于提高性能——————————————————————————-%CFLAGS=”-O6-mpentiumpro-fomit-frame-pointer”CXX=gccCXXFLAGS=”-O6-mpentiumpro-fomit-frame-pointer-felide-constructors-fno-exceptions-fno-rtti”./configure–prefix=/usr/local–enable-assembler–with-mysqld-ldflags=-all-static–disable-shared
二、调整服务器确保运用正确的编译固然重要,但这只是成功的第一步,配置众多的MySQL变量同样对服务器的正常运行起关键作用你可以将这些变量的赋值存在一个配置文件中,以确保它们在每次启动MySQL时均起作用,这个配置文件就是my.cnf文件MySQL已经提供了几个my.cnf文件的样本,可在/usr/local/mysqld/share/mysql/目录下找到这些文件分别命名为my-small.cnf、my-medium.cnf、my-large.cnf和my-huge.cnf,规模说明可在描述配置文件适用的系统类型标题中找到如果在只有相当少内存的系统上运行MySQL,而且只是偶尔的用一下,那么my-small.cnf会比较理想,因为它命令mysqld只使用最少的资源类似地,如果你计划构建电子商务超市,而且系统拥有2G内存,那么你可能要用到mysql-huge.cnf文件了为了利用这些文件中的一个,你需要复制一个最适合需求的文件,改名为my.cnf你可以选择使用配置文件三种作用范围的一种Global将my.cnf文件复制到服务器的/etc目录下,这使得配置文件中的变量作用于全局,即对所有服务器上的MySQL数据库服务器有效Local将my.cnf文件复制到[MYSQL-INSTALL-DIR]/var/目录下,使得my.cnf作用于特定的服务器[MYSQL-INSTALL-DIR]表示MySQL安装目录User你可以再限制作用于特定的用户,将my.cnf复制到用户的根目录下究竟如何设置my.cnf中的这些变量呢?更进一步说,你可以设置哪一个变量虽然所用变量对MySQL服务器相对通用,每一个变量与MySQL的的某些组件有更特定的关系如变量max_connects归在mysqld类别下执行下列命令即可知道——————————————————————————–%/usr/local/mysql/libexec/mysqld–help——————————————————————————–它显示大量的选项及与mysqld相关的变量你可以很容易地在该行文字之下找出变量——————————————————————————–Possiblevariablesforoption–set-variable-Oare——————————————————————————–然后你可以如下设置my.cnf中的那些变量——————————————————————————–set-variable=max_connections=100——————————————————————————–它设置MySQL服务器的最大并发连接数为100要确保在my.cnf文件中的[mysqld]标题下插入变量设置
三、表类型很多MySQL用户可能很惊讶,MySQL确实为用户提供5种不同的表类型,称为DBD、HEAP、ISAM、MERGE和MyIASMDBD归为事务安全类,而其他为非事务安全类
3.
1、事务安全DBDBerkeleyDBDBD表是支持事务处理的表,由Sleepycat软件公司开发它提供MySQL用户期待已久的功能-事务控制事务控制在任何数据库系统中都是一个极有价值的功能,因为它们确保一组命令能成功地执行
3.
2、非事务安全HEAPHEAP表是MySQL中存取数据最快的表这是因为他们使用存储在动态内存中的一个哈希索引另一个要点是如果MySQL或服务器崩溃,数据将丢失ISAMISAM表是早期MySQL版本的缺省表类型,直到MyIASM开发出来建议不要再使用它MERGEMERGE是一个有趣的新类型,在之后出现一个MERGE表实际上是一个相同MyISAM表的集合,合并成一个表,主要是为了效率原因这样可以提高速度、搜索效率、修复效率并节省磁盘空间MyIASM这是MySQL的缺省表类型它基于IASM代码,但有很多有用的扩展MyIASM比较好的原因MyIASM表小于IASM表,所以使用较少资源MyIASM表在不同的平台上二进制层可移植更大的键码尺寸,更大的键码上限
3.
3、指定表类型你可在创建表时指定表的类型下例创建一个HEAP表——————————————————————————–mysqlCREATETABLEemail_addressesTYPE=HEAP-emailchar55NOTNULL-namechar30NOTNULL-PRIMARYKEYemail;——————————————————————————–BDB表需要一些配置工作,参见
3.
4、更多的表类型为了使MySQL管理工作更有趣,即将发布的MySQL
4.0将提供两种新的表类型,称为Innobase和Gemeni
4、优化工具MySQL服务器本身提供了几条内置命令用于帮助优化
4.
1、SHOW你可能有兴趣知道MySQL服务器究竟更了什么,下列命令给出一个总结——————————————————————————–mysqlshowstatus;——————————————————————————–它给出了一个相当长的状态变量及其值的列表有些变量包含了异常终止客户的数量、异常终止连接的数量、连接尝试的次数、最大并发连接数和大量其他有用的信息这些信息对找出系统问题和低效极具价值SHOW还能做更多的事情它可以显示关于日志文件、特定数据库、表、索引、进程和权限表中有价值的信息详见MySQL手册
4.
2、EXPLAIN当你面对SELECT语句时,EXPLAIN解释SELECT命令如何被处理这不仅对决定是否应该增加一个索引,而且对决定一个复杂的Join如何被MySQL处理都是有帮助的
4.
3、OPTIMIZEOPTIMIZE语句允许你恢复空间和合并数据文件碎片,对包含变长行的表进行了大量更新和删除后,这样做特别重要OPTIMIZE目前只工作于MyIASM和BDB表
8、小小+霸霸+王王=小霸王小=霸=王=用sql求证参考答案:declare@dataint@iint@jint@lintset@data=100while@data=999beginset@i=@data/100set@j=@data/10%10set@l=@data%10if@i+@j+@l*11=@databeginSelect@datadata@ii@jj@llbreakendset@data=@data+1end;分析II+JJ+LL=IJLI*10+I+J*10+J+L*10+L=I*100+J*10+LI+J+L*
119、几个面试题,没有答案:
1、一张表里面有ID自增主键当insert了17条记录之后删除了第151617条记录再把Mysql重启再insert一条记录这条记录的ID是18还是
152、一张表有还是有ID自增主键用JDBCinsert一条语句之内怎么在JAVA程序里面获得这条记录的ID.
10、Mysql支持实物答案在缺省模式下,MYSQL是autocommit模式的,所有的数据库更新操作都会即时提交,所以在缺省情况下,mysql是不支持事务的但是如果你的MYSQL表类型是使用InnoDBTables或BDBtables的话,你的MYSQL就可以使用事务处理使用SETAUTOCOMMIT=0就可以使MYSQL允许在非autocommit模式,在非autocommit模式下,你必须使用COMMIT来提交你的更改,或者用ROLLBACK来回滚你的更改示例如下STARTTRANSACTION;SELECT@A:=SUMsalaryFROMtable1WHEREtype=1;UPDATEtable2SETsummmary=@AWHEREtype=1;COMMIT;
11、MysQL有关权限表都有几个答案MySQL服务器通过权限表来控制用户对数据库的访问,权限表存放在mysql数据库里,由mysql_install_db脚本初始化这些权限表分别user,db,table_priv,columns_priv和host下面分别介绍一下这些表的结构和内容user权限表记录允许连接到服务器的用户帐号信息,里面的权限是全局级的db权限表记录各个帐号在各个数据库上的操作权限table_priv权限表记录数据表级的操作权限columns_priv权限表记录数据列级的操作权限host权限表配合db权限表对给定主机上数据库级操作权限作更细致的控制这个权限表不受GRANT和REVOKE语句的影响
12、介绍MySql的时间函数答案这里是一个使用日期函数的例子下面的查询选择所有date_col值在最后30天内的记录mysqlSELECTsomethingFROMtbl_nameWHERETO_DAYSNOW–TO_DAYSdate_col=30;DAYOFWEEKdate返回date的星期索引1=Sunday2=Monday...7=Saturday索引值符合ODBC的标准mysqlSELECTDAYOFWEEK’1998-02-03′;-3WEEKDAYdate返回date的星期索引0=Monday1=Tuesday…6=Sunday mysqlSELECTWEEKDAY’1998-02-0322:23:00′;-1mysqlSELECTWEEKDAY’1997-11-05′;-2DAYOFMONTHdate返回date是一月中的第几天,范围为1到31mysqlSELECTDAYOFMONTH’1998-02-03′;-3DAYOFYEARdate返回date是一年中的第几天,范围为1到366mysqlSELECTDAYOFYEAR’1998-02-03′;-34MONTHdate返回date中的月份,范围为1到12mysqlSELECTMONTH’1998-02-03′;-2DAYNAMEdate返回date的星期名mysqlSELECTDAYNAME“1998-02-05″;-‘Thursday’MONTHNAMEdate返回date的月份名mysqlSELECTMONTHNAME“1998-02-05″;-‘February’QUARTERdate返回date在一年中的季度,范围为1到4mysqlSELECTQUARTER’98-04-01′;-2WEEKdateWEEKdatefirst对于星期日是一周中的第一天的场合,如果函数只有一个参数调用,返回date为一年的第几周,返回值范围为0到53是的,可能有第53周的开始两个参数形式的WEEK允许你指定一周是否以星期日或星期一开始,以及返回值为0-53还是1-52这里的一个表显示第二个参数是如何工作的值含义0一周以星期日开始,返回值范围为0-531一周以星期一开始,返回值范围为0-532一周以星期日开始,返回值范围为1-533一周以星期一开始,返回值范围为1-53ISO8601mysqlSELECTWEEK’1998-02-20′;-7mysqlSELECTWEEK’1998-02-20′0;-7mysqlSELECTWEEK’1998-02-20′1;-8mysqlSELECTWEEK’1998-12-31′1;-53注意,在版本
4.0中,WEEK#0被更改为匹配USA历法注意,如果一周是上一年的最后一周,当你没有使用2或3做为可选参数时,MySQL将返回0mysqlSELECTYEAR’2000-01-01′WEEK’2000-01-01′0;-20000mysqlSELECTWEEK’2000-01-01′2;-52你可能会争辩说,当给定的日期值实际上是1999年的第52周的一部分时,MySQL对WEEK函数应该返回52我们决定返回0,是因为我们希望该函数返回“在指定年份中是第几周”当与其它的提取日期值中的月日值的函数结合使用时,这使得WEEK函数的用法可靠如果你更希望能得到恰当的年-周值,那么你应该使用参数2或3做为可选参数,或者使用函数YEARWEEK mysqlSELECTYEARWEEK’2000-01-01′;-199952mysqlSELECTMIDYEARWEEK’2000-01-01′52;-52YEARdate返回date的年份,范围为1000到9999mysqlSELECTYEAR’98-02-03′;-1998YEARWEEKdateYEARWEEKdatefirst返回一个日期值是的哪一年的哪一周第二个参数的形式与作用完全与WEEK的第二个参数一致注意,对于给定的日期参数是一年的第一周或最后一周的,返回的年份值可能与日期参数给出的年份不一致mysqlSELECTYEARWEEK’1987-01-01′;-198653注意,对于可选参数0或1,周值的返回值不同于WEEK函数所返回值0,WEEK根据给定的年语境返回周值HOURtime返回time的小时值,范围为0到23mysqlSELECTHOUR’10:05:03′;-10MINUTEtime返回time的分钟值,范围为0到59mysqlSELECTMINUTE’98-02-0310:05:03′;-5SECONDtime返回time的秒值,范围为0到59mysqlSELECTSECOND’10:05:03′;-3PERIOD_ADDPN增加N个月到时期P格式为YYMM或YYYYMM中以YYYYMM格式返回值注意,期间参数P不是一个日期值mysqlSELECTPERIOD_ADD98012;-199803PERIOD_DIFFP1P2返回时期P1和P2之间的月数P1和P2应该以YYMM或YYYYMM指定注意,时期参数P1和P2不是日期值mysqlSELECTPERIOD_DIFF9802199703;-11DATE_ADDdateINTERVALexprtypeDATE_SUBdateINTERVALexprtypeADDDATEdateINTERVALexprtypeSUBDATEdateINTERVALexprtype这些函数执行日期的算术运算ADDDATE和SUBDATE分别是DATE_ADD和DATE_SUB的同义词在MySQL
3.23中,如果表达式的右边是一个日期值或一个日期时间型字段,你可以使用+和–代替DATE_ADD和DATE_SUB示例如下参数date是一个DATETIME或DATE值,指定一个日期的开始expr是一个表达式,指定从开始日期上增加还是减去间隔值expr是一个字符串;它可以以一个“-”领头表示一个负的间隔值type是一个关键词,它标志着表达式以何格式被解释下表显示type和expr参数是如何关联的type值expr期望的格式SECONDSECONDSMINUTEMINUTESHOURHOURSDAYDAYSMONTHMONTHSYEARYEARSMINUTE_SECOND“MINUTES:SECONDS”HOUR_MINUTE“HOURS:MINUTES”DAY_HOUR“DAYSHOURS”YEAR_MONTH“YEARS-MONTHS”HOUR_SECOND“HOURS:MINUTES:SECONDS”DAY_MINUTE“DAYSHOURS:MINUTES”DAY_SECOND“DAYSHOURS:MINUTES:SECONDS”在expr的格式中,MySQL允许任何字符作为定界符表中所显示的是建议的定界字符如果date参数是一个DATE值,并且计算的间隔仅仅有YEAR、MONTH和DAY部分没有时间部分,那么返回值也是一个DATE值否则返回值是一个DATETIME值mysqlSELECT“1997-12-3123:59:59″+INTERVAL1SECOND;-1998-01-0100:00:00mysqlSELECTINTERVAL1DAY+“1997-12-31″;-1998-01-01mysqlSELECT“1998-01-01″–INTERVAL1SECOND;-1997-12-3123:59:59mysqlSELECTDATE_ADD“1997-12-3123:59:59″-INTERVAL1SECOND;-1998-01-0100:00:00mysqlSELECTDATE_ADD“1997-12-3123:59:59″-INTERVAL1DAY;-1998-01-0123:59:59mysqlSELECTDATE_ADD“1997-12-3123:59:59″-INTERVAL“1:1″MINUTE_SECOND;-1998-01-0100:01:00mysqlSELECTDATE_SUB“1998-01-0100:00:00″-INTERVAL“11:1:1″DAY_SECOND;-1997-12-3022:58:59mysqlSELECTDATE_ADD“1998-01-0100:00:00″-INTERVAL“-110″DAY_HOUR;-1997-12-3014:00:00mysqlSELECTDATE_SUB“1998-01-02″INTERVAL31DAY;-1997-12-02如果你指定了一个太短的间隔值没有包括type关键词所期望的所有间隔部分,MySQL假设你遗漏了间隔值的最左边部分例如,如果指定一个type为DAY_SECOND,那么expr值被期望包含天、小时、分钟和秒部分如果你象“1:10″样指定一个值,MySQL假设天和小时部分被遗漏了,指定的值代表分钟和秒换句话说,”1:10″DAY_SECOND被解释为等价于“1:10″MINUTE_SECOND这类似于MySQL解释TIME值为经过的时间而不是一天的时刻注意,如果依着包含一个时间部分的间隔增加或减少一个日期值,该日期值将被自动地转换到一个日期时间值mysqlSELECTDATE_ADD“1999-01-01″INTERVAL1DAY;-1999-01-02mysqlSELECTDATE_ADD“1999-01-01″INTERVAL1HOUR;-1999-01-0101:00:00如果你使用了确定不正确的日期,返回结果将是NULL如果你增加MONTH、YEAR_MONTH或YEAR,并且结果日期的天比新月份的最大天数还大,那么它将被调整到新月份的最大天数mysqlSELECTDATE_ADD’1998-01-30′INTERVAL1MONTH;-1998-02-28注意,上面的例子中,单词INTERVAL和关键词type是不区分字母大小写的EXTRACTtypeFROMdateEXTRACT函数使用与DATE_ADD或DATE_SUB一致的间隔类型,但是它用于指定从日期中提取的部分,而不是进行日期算术运算mysqlSELECTEXTRACTYEARFROM“1999-07-02″;-1999mysqlSELECTEXTRACTYEAR_MONTHFROM“1999-07-0201:02:03″;-199907mysqlSELECTEXTRACTDAY_MINUTEFROM“1999-07-0201:02:03″;-20102TO_DAYSdate给出一个日期date,返回一个天数从0年开始的天数mysqlSELECTTO_DAYS950501;-728779mysqlSELECTTO_DAYS’1997-10-07′;-729669TO_DAYS无意于使用先于格里高里历法即现行的阳历1582出现的值,因为它不考虑当历法改变时所遗失的天数FROM_DAYSN给出一个天数N,返回一个DATE值mysqlSELECTFROM_DAYS729669;-’1997-10-07′FROM_DAYS无意于使用先于格里高里历法1582出现的值,因为它不考虑当历法改变时所遗失的天数DATE_FORMATdateformat依照format字符串格式化date值下面的修饰符可被用于format字符串中修饰符含义%M月的名字January..December%W星期的名字Sunday..Saturday%D有英文后缀的某月的第几天0th1st2nd3rdetc.%Y年份,数字的,4位%y年份,数字的,2位%X周值的年份,星期日是一个星期的第一天,数字的,4位,与‘%V’一同使用%x周值的年份,星期一是一个星期的第一天,数字的,4位,与‘%v’一同使用%a缩写的星期名Sun..Sat%d月份中的天数,数字的
00..31%e月份中的天数,数字的
0..31%m月,数字的
00..12%c月,数字的
0..12%b缩写的月份名Jan..Dec%j一年中的天数
001..366%H小时
00..23%k小时
0..23%h小时
01..12%I小时
01..12%l小时
1..12%i分钟,数字的
00..59%r时间,12小时hh:mm:ss[AP]M%T时间,24小时hh:mm:ss%S秒
00..59%s秒
00..59%pAM或PM%w一周中的天数0=Sunday..6=Saturday%U星期
00..53,星期日是一个星期的第一天%u星期
00..53,星期一是一个星期的第一天%V星期
01..53,星期日是一个星期的第一天与‘%X’一起使用%v星期
01..53,星期一是一个星期的第一天与‘%x’一起使用%%一个字母“%”所有其它的字符不经过解释,直接复制到结果中mysqlSELECTDATE_FORMAT’1997-10-0422:23:00′‘%W%M%Y’;-‘SaturdayOctober1997′mysqlSELECTDATE_FORMAT’1997-10-0422:23:00′‘%H:%i:%s’;-’22:23:00′mysqlSELECTDATE_FORMAT’1997-10-0422:23:00′‘%D%y%a%d%m%b%j’;-’4th97Sat0410Oct277′mysqlSELECTDATE_FORMAT’1997-10-0422:23:00′‘%H%k%I%r%T%S%w’;-’22221010:23:00PM22:23:00006′mysqlSELECTDATE_FORMAT’1999-01-01′‘%X%V’;-’199852′在MySQL
3.23中,在格式修饰符前需要字符`%’在更早的MySQL版本中,`%’是可选的月份与天修饰符的范围从零开始的原因是,在MySQL
3.23中,它允许存储不完善的日期值例如’2004-00-00′TIME_FORMATtimeformat它的使用方法与上面的DATE_FORMAT函数相似,但是format字符串只包含处理小时、分和秒的那些格式修饰符使用其它的修饰符会产生一个NULL值或0CURDATECURRENT_DATE以‘YYYY-MM-DD’或YYYYMMDD格式返回当前的日期值,返回的格式取决于该函数是用于字符串还是数字语境中mysqlSELECTCURDATE;-’1997-12-15′mysqlSELECTCURDATE+0;-19971215CURTIMECURRENT_TIME以‘HH:MM:SS’或HHMMSS格式返回当前的时间值,返回的格式取决于该函数是用于字符串还是数字语境中mysqlSELECTCURTIME;-’23:50:26′mysqlSELECTCURTIME+0;-235026NOWSYSDATECURRENT_TIMESTAMP以‘YYYY-MM-DDHH:MM:SS’或YYYYMMDDHHMMSS格式返回当前的日期时间值,返回的格式取决于该函数是用于字符串还是数字语境中mysqlSELECTNOW;-’1997-12-1523:50:26′mysqlSELECTNOW+0;注意,函数NOW在每个查询中只计算一次,也就是在查询开始执行时这就是说,如果在一个单独的查询中多次引用了NOW,它只会给出值都是一个相同的时间UNIX_TIMESTAMPUNIX_TIMESTAMPdate如果调用时没有参数,以无符号的整数形式返回一个Unix时间戳从’1970-01-0100:00:00′GMT开始的秒数如果以一个参数date调用UNIX_TIMESTAMP,它将返回该参数值从’1970-01-0100:00:00′GMT开始经过的秒数值date可以是一个DATE字符串,一个DATETIME字符串,一个TIMESTAMP,或者以一个YYMMDD或YYYYMMDD显示的本地时间mysqlSELECTUNIX_TIMESTAMP;-882226357mysqlSELECTUNIX_TIMESTAMP’1997-10-0422:23:00′;-875996580当UNIX_TIMESTAMP被用于一个TIMESTAMP列时,函数直接返回一个内部的时间戳值,而不进行一个隐含地“string-to-unix-timestamp”转换如果你传递一个超出范围的日期参数给UNIX_TIMESTAMP,它将返回0,但是请注意,MySQL对其仅仅进行基本的检验年范围1970-2037,月份01-12,日期01-31如果你希望减去UNIX_TIMESTAMP列,你应该需要将结果强制转换为一有符号整数查看章节函数FROM_UNIXTIMEunix_timestamp[format]以‘YYYY-MM-DDHH:MM:SS’或YYYYMMDDHHMMSS格式返回一个unix_timestamp参数值,返回值的形式取决于该函数使用于字符串还是数字语境如果format给出,返回值依format字符串被格式format可以包含与DATE_FORMAT函数同样的修饰符mysqlSELECTFROM_UNIXTIME875996580;-’1997-10-0422:23:00′mysqlSELECTFROM_UNIXTIME875996580+0;mysqlSELECTFROM_UNIXTIMEUNIX_TIMESTAMP‘%Y%D%M%h:%i:%s%x’;-’199723rdDecember03:43:301997′SEC_TO_TIMEseconds以‘HH:MM:SS’或HHMMSS格式返回参数seconds被转换到时分秒后的值,返回值的形式取决于该函数使用于字符串还是数字语境mysqlSELECTSEC_TO_TIME2378;-’00:39:38′mysqlSELECTSEC_TO_TIME2378+0;-3938TIME_TO_SECtime将参数time转换为秒数后返回mysqlSELECTTIME_TO_SEC’22:23:00′;-80580mysqlSELECTTIME_TO_SEC’00:39:38′;-
237813、常用优化技巧答案MySQL自带slowlog的分析工具mysqldumpslow,但是没有说明本文通过分析该脚本,介绍了其用法slowlog是MySQL根据SQL语句的执行时间设定,写入的一个文件,用于分析执行较慢的语句只要在my.cnf文件中配置好log-slow-queries=[slow_query_log_filename]即可记录超过默认的10s执行时间的SQL语句如果要修改默认设置,可以添加long_query_time=5设定为5s如果要记录所有SQL语句,可以写入log-long-format#t=timel=locktimer=rows#atal以及ar是对应的平均值mysqldumpslow可以接受的参数有‘v+’#verbose‘d+’#debug‘s=s’#排序tatlalraretc‘r!’#倒排序largestlastinsteadoffirst‘t=i’#显示最高的n个查询‘a!’#不把所有的数字以N,字符串以‘S’显示‘n=i’#abstractnumberswithatleastndigitswithinnames‘g=s’#grep:onlyconsiderstmtsthatincludethisstring‘h=s’#hostnameofdbserverfor*-slow.logfilenamecanbewildcard‘i=s’#nameofserverinstanceifusingmysql.serverstartupscript‘l!’#don’tsubtractlocktimefromtotaltimemysqlexplain的使用说明explain显示了mysql如何使用索引来处理select语句以及连接表可以帮助选择更好的索引和写出更优化的查询语句使用方法,在select语句前加上explain就可以了如explainselectsurnamefirst_nameformabwherea.id=b.id分析结果形式如下引用mysqlexplainSELECT*FROM`whisper`WHEREto_id=6696ANDdel=0ANDwhisper=0ORDERBY`send_time`DESCLIMIT4;+—-+————-+———+——+—————+——-+———+——-+——+—————————–+|id|select_type|table|type|possible_keys|key|key_len|ref|rows|Extra|+—-+————-+———+——+—————+——-+———+——-+——+—————————–+|1|SIMPLE|whisper|ref|to_id|to_id|4|const|1|Usingwhere;Usingfilesort|+—-+————-+———+——+—————+——-+———+——-+——+—————————–+1rowinset
0.00secEXPLAIN列的解释table显示这一行的数据是关于哪张表的type这是重要的列,显示连接使用了何种类型从最好到最差的连接类型为const、eq_reg、ref、range、indexhe和ALLpossible_keys显示可能应用在这张表中的索引如果为空,没有可能的索引可以为相关的域从WHERE语句中选择一个合适的语句key实际使用的索引如果为NULL,则没有使用索引很少的情况下,MYSQL会选择优化不足的索引这种情况下,可以在SELECT语句中使用USEINDEX(indexname)来强制使用一个索引或者用IGNOREINDEX(indexname)来强制MYSQL忽略索引key_len使用的索引的长度在不损失精确性的情况下,长度越短越好ref显示索引的哪一列被使用了,如果可能的话,是一个常数rowsMYSQL认为必须检查的用来返回请求数据的行数Extra关于MYSQL如何解析查询的额外信息将在表
4.3中讨论,但这里可以看到的坏的例子是Usingtemporary和Usingfilesort,意思MYSQL根本不能使用索引,结果是检索会很慢extra列返回的描述的意义Distinct一旦MYSQL找到了与行相联合匹配的行,就不再搜索了NotexistsMYSQL优化了LEFTJOIN,一旦它找到了匹配LEFTJOIN标准的行,就不再搜索了RangecheckedforeachRecord(indexmap:#)没有找到理想的索引,因此对于从前面表中来的每一个行组合,MYSQL检查使用哪个索引,并用它来从表中返回行这是使用索引的最慢的连接之一Usingfilesort看到这个的时候,查询就需要优化了MYSQL需要进行额外的步骤来发现如何对返回的行排序它根据连接类型以及存储排序键值和匹配条件的全部行的行指针来排序全部行Usingindex列数据是从仅仅使用了索引中的信息而没有读取实际的行动的表返回的,这发生在对表的全部的请求列都是同一个索引的部分的时候Usingtemporary看到这个的时候,查询需要优化了这里,MYSQL需要创建一个临时表来存储结果,这通常发生在对不同的列集进行ORDERBY上,而不是GROUPBY上Whereused使用了WHERE从句来限制哪些行将与下一张表匹配或者是返回给用户如果不想返回表中的全部行,并且连接类型ALL或index,这就会发生,或者是查询有问题不同连接类型的解释(按照效率高低的顺序排序)system表只有一行system表这是const连接类型的特殊情况const表中的一个记录的最大值能够匹配这个查询(索引可以是主键或惟一索引)因为只有一行,这个值实际就是常数,因为MYSQL先读这个值然后把它当做常数来对待eq_ref在连接中,MYSQL在查询时,从前面的表中,对每一个记录的联合都从表中读取一个记录,它在查询使用了索引为主键或惟一键的全部时使用ref这个连接类型只有在查询使用了不是惟一或主键的键或者是这些类型的部分(比如,利用最左边前缀)时发生对于之前的表的每一个行联合,全部记录都将从表中读出这个类型严重依赖于根据索引匹配的记录多少—越少越好range这个连接类型使用索引返回一个范围中的行,比如使用或查找东西时发生的情况index这个连接类型对前面的表中的每一个记录联合进行完全扫描(比ALL更好,因为索引一般小于表数据)ALL这个连接类型对于前面的每一个记录联合进行完全扫描,这一般比较糟糕,应该尽量避免mysql常用的hint(原创)mysql常用的hint对于经常使用oracle的朋友可能知道,oracle的hint功能种类很多,对于优化sql语句提供了很多方法同样,在mysql里,也有类似的hint功能下面介绍一些常用的[b]强制索引FORCEINDEX[/b]SELECT*FROMTABLE1FORCEINDEXFIELD1…以上的SQL语句只使用建立在FIELD1上的索引,而不使用其它字段上的索引[b]忽略索引IGNOREINDEX[/b]SELECT*FROMTABLE1IGNOREINDEXFIELD1FIELD2…在上面的SQL语句中,TABLE1表中FIELD1和FIELD2上的索引不被使用[b]关闭查询缓冲SQL_NO_CACHE[/b]SELECTSQL_NO_CACHEfield1field2FROMTABLE1;有一些SQL语句需要实时地查询数据,或者并不经常使用(可能一天就执行一两次)这样就需要把缓冲关了不管这条SQL语句是否被执行过,服务器都不会在缓冲区中查找,每次都会执行它[b]强制查询缓冲SQL_CACHE[/b]SELECTSQL_CALHE*FROMTABLE1;如果在my.ini中的query_cache_type设成2,这样只有在使用了SQL_CACHE后,才使用查询缓冲[b]优先操作HIGH_PRIORITY[/b]HIGH_PRIORITY可以使用在select和insert操作中,让MYSQL知道,这个操作优先进行SELECTHIGH_PRIORITY*FROMTABLE1;[b]滞后操作LOW_PRIORITY[/b]LOW_PRIORITY可以使用在insert和update操作中,让mysql知道,这个操作滞后updateLOW_PRIORITYtable1setfield1=wherefield1=…[b]延时插入INSERTDELAYED[/b]INSERTDELAYEDINTOtable1setfield1=…INSERTDELAYEDINTO,是客户端提交数据给MySQL,MySQL返回OK状态给客户端而这是并不是已经将数据插入表,而是存储在内存里面等待排队当mysql有空余时,再插入另一个重要的好处是,来自许多客户端的插入被集中在一起,并被编写入一个块这比执行许多独立的插入要快很多坏处是,不能返回自动递增的ID,以及系统崩溃时,MySQL还没有来得及插入数据的话,这些数据将会丢失[b]强制连接顺序STRAIGHT_JOIN[/b]SELECTTABLE
1.FIELD1TABLE
2.FIELD2FROMTABLE1STRAIGHT_JOINTABLE2WHERE…由上面的SQL语句可知,通过STRAIGHT_JOIN强迫MySQL按TABLE
1、TABLE2的顺序连接表如果你认为按自己的顺序比MySQL推荐的顺序进行连接的效率高的话,就可以通过STRAIGHT_JOIN来确定连接顺序[b]强制使用临时表SQL_BUFFER_RESULT[/b]SELECTSQL_BUFFER_RESULT*FROMTABLE1WHERE…当我们查询的结果集中的数据比较多时,可以通过SQL_BUFFER_RESULT.选项强制将结果集放到临时表中,这样就可以很快地释放MySQL的表锁(这样其它的SQL语句就可以对这些记录进行查询了),并且可以长时间地为客户端提供大记录集[b]分组使用临时表SQL_BIG_RESULT和SQL_SMALL_RESULT[/b]SELECTSQL_BUFFER_RESULTFIELD1COUNT*FROMTABLE1GROUPBYFIELD1;一般用于分组或DISTINCT关键字,这个选项通知MySQL,如果有必要,就将查询结果放到临时表中,甚至在临时表中进行排序SQL_SMALL_RESULT比起SQL_BIG_RESULT差不多,很少使用查询是数据库技术中最常用的操作查询操作的过程比较简单,首先从客户端发出查询的SQL语句,数据库服务端在接收到由客户端发来的SQL语句后,执行这条SQL语句,然后将查询到的结果返回给客户端虽然过程很简单,但不同的查询方式和数据库设置,对查询的性能将会有很在的影响因此,本文就在MySQL中常用的查询优化技术进行讨论讨论的内容如通过查询缓冲提高查询速度;MySQL对查询的自动优化;基于索引的排序;不可达查询的检测和使用各种查询选择来提高性能
一、通过查询缓冲提高查询速度一般我们使用SQL语句进行查询时,数据库服务器每次在收到客户端发来SQL后,都会执行这条SQL语句但当在一定间隔内如1分钟内,接到完全一样的SQL语句,也同样执行它虽然这样可以保证数据的实时性,但在大多数时候,数据并不要求完全的实时,也就是说可以有一定的延时如果是这样的话,在短时间内执行完全一样的SQL就有些得不偿失幸好MySQL为我们提供了查询缓冲的功能只能在及以上版本使用查询缓冲我们可以通过查询缓冲在一定程度上提高查询性能我们可以通过在MySQL安装目录中的my.ini文件设置查询缓冲设置也非常简单,只需要将query_cache_type设为1即可在设置了这个属性后,MySQL在执行任何SELECT语句之前,都会在它的缓冲区中查询是否在相同的SELECT语句被执行过,如果有,并且执行结果没有过期,那么就直接取查询结果返回给客户端但在写SQL语句时注意,MySQL的查询缓冲是区分大小写的如下列的两条SELECT语句:
1.SELECT*fromTABLE
12.
3.SELECT*FROMTABLE1上面的两条SQL语句对于查询缓冲是完全不同的SELECT而且查询缓冲并不自动处理空格,因此,在写SQL语句时,应尽量减少空格的使用,尤其是在SQL首和尾的空格因为,查询缓冲并不自动截取首尾空格虽然不设置查询缓冲,有时可能带来性能上的损失,但有一些SQL语句需要实时地查询数据,或者并不经常使用可能一天就执行一两次这样就需要把缓冲关了当然,这可以通过设置query_cache_type的值来关闭查询缓冲,但这就将查询缓冲永久地关闭了在MySQL
5.0中提供了一种可以临时关闭查询缓冲的方法:
1.SELECTSQL_NO_CACHEfield1field2FROMTABLE1以上的SQL语句由于使用了SQL_NO_CACHE,因此,不管这条SQL语句是否被执行过,服务器都不会在缓冲区中查找,每次都会执行它我们还可以将my.ini中的query_cache_type设成2,这样只有在使用了SQL_CACHE后,才使用查询缓冲
1.SELECTSQL_CALHE*FROMTABLE1
二、MySQL对查询的自动优化索引对于数据库是非常重要的在查询时可以通过索引来提高性能但有时使用索引反而会降低性能我们可以看如下的SALES表:
1.CREATETABLESALES
2.
3.
4.
5.IDINT10UNSIGNEDNOTNULLAUTO_INCREMENT
6.
7.NAMEVARCHAR100NOTNULL
8.
9.PRICEFLOATNOTNULL
10.
11.SALE_COUNTINTNOTNULL
12.
13.SALE_DATEDATENOTNULL
14.
15.PRIMARYKEYID,
16.
17.INDEXNAME,
18.
19.INDEXSALE_DATE
20.
21.;假设这个表中保存了数百万条数据,而我们要查询商品号为1000的商品在2004年和2005年的平均价格我们可以写如下的SQL语句:SELECTAVGPRICEFROMSALESWHEREID=1000ANDSALE_DATEBETWEEN’2004-01-01′AND’2005-12-31′;如果这种商品的数量非常多,差不多占了SALES表的记录的50%或更多那么使用SALE_DATE字段上索引来计算平均数就有些慢因为如果使用索引,就得对索引进行排序操作当满足条件的记录非常多时如占整个表的记录的50%或更多的比例,速度会变慢,这样还不如对整个表进行扫描因此,MySQL会自动根据满足条件的数据占整个表的数据的比例自动决定是否使用索引进行查询对于MySQL来说,上述的查询结果占整个表的记录的比例是30%左右时就不使用索引了,这个比例是MySQL的开发人员根据他们的经验得出的然而,实际的比例值会根据所使用的数据库引擎不同而不同
三、基于索引的排序MySQL的弱点之一是它的排序虽然MySQL可以在1秒中查询大约15000条记录,但由于MySQL在查询时最多只能使用一个索引因此,如果WHERE条件已经占用了索引,那么在排序中就不使用索引了,这将大大降低查询的速度我们可以看看如下的SQL语句:
1.SELECT*FROMSALESWHERENAME=“name”ORDERBYSALE_DATEDESC;在以上的SQL的WHERE子句中已经使用了NAME字段上的索引,因此,在对SALE_DATE进行排序时将不再使用索引为了解决这个问题,我们可以对SALES表建立复合索引:
1.ALTERTABLESALESDROPINDEXNAMEADDINDEXNAMESALE_DATE这样再使用上述的SELECT语句进行查询时速度就会大副提升但要注意,在使用这个方法时,要确保WHERE子句中没有排序字段,在上例中就是不能用SALE_DATE进行查询,否则虽然排序快了,但是SALE_DATE字段上没有单独的索引,因此查询又会慢下来
四、不可达查询的检测在执行SQL语句时,难免会遇到一些必假的条件所谓必假的条件是无论表中的数据如何变化,这个条件都为假如WHEREvalue100ANDvalue200我们永远无法找到一个既小于100又大于200的数如果遇到这样的查询条件,再去执行这样的SQL语句就是多此一举幸好MySQL可以自动检测这种情况如我们可以看看如下的SQL语句:
1.SELECT*FROMSALESWHERENAME=“name1”ANDNAME=“name2”以上的查询语句要查找NAME既等于name1又等于name2的记录很明显,这是一个不可达的查询,WHERE条件一定是假MySQL在执行SQL语句之前,会先分析WHERE条件是否是不可达的查询,如果是,就不再执行这条SQL语句了为了验证这一点我们首先对如下的SQL使用EXPLAIN进行测试:
1.EXPLAINSELECT*FROMSALESWHERENAME=“name1”上面的查询是一个正常的查询,我们可以看到使用EXPLAIN返回的执行信息数据中table项是SALES这说明MySQL对SALES进行操作了再看看下面的语句:
1.EXPLAINSELECT*FROMSALESWHERENAME=“name1”ANDNAME=“name2”我们可以看到,table项是空,这说明MySQL并没有对SALES表进行操作
五、使用各种查询选择来提高性能SELECT语句除了正常的使用外,MySQL还为我们提供了很多可以增强查询性能的选项如上面介绍的用于控制查询缓冲的SQL_NO_CACHE和SQL_CACHE就是其中两个选项在这一部分,我将介绍几个常用的查询选项
1.STRAIGHT_JOIN:强制连接顺序当我们将两个或多个表连接起来进行查询时,我们并不用关心MySQL先连哪个表,后连哪个表而这一切都是由MySQL内部通过一系列的计算、评估,最后得出的一个连接顺序决定的如下列的SQL语句中,TABLE1和TABLE2并不一定是谁连接谁:
1.SELECTTABLE
1.FIELD1TABLE
2.FIELD2FROMTABLE1TABLE2WHERE…如果开发人员需要人为地干预连接的顺序,就得使用STRAIGHT_JOIN关键字,如下列的SQL语句:
1.SELECTTABLE
1.FIELD1TABLE
2.FIELD2FROMTABLE1STRAIGHT_JOINTABLE2WHERE…由上面的SQL语句可知,通过STRAIGHT_JOIN强迫MySQL按TABLE
1、TABLE2的顺序连接表如果你认为按自己的顺序比MySQL推荐的顺序进行连接的效率高的话,就可以通过STRAIGHT_JOIN来确定连接顺序
2.干预索引使用,提高性能在上面已经提到了索引的使用一般情况下,在查询时MySQL将自己决定是否使用索引,使用哪一个索引但在一些特殊情况下,我们希望MySQL只使用一个或几个索引,或者不希望使用某个索引这就需要使用MySQL的控制索引的一些查询选项限制使用索引的范围有时我们在数据表里建立了很多索引,当MySQL对索引进行选择时,这些索引都在考虑的范围内但有时我们希望MySQL只考虑几个索引,而不是全部的索引,这就需要用到USEINDEX对查询语句进行设置
1.SELECT*FROMTABLE1USEINDEXFIELD1FIELD2…从以上SQL语句可以看出,无论在TABLE1中已经建立了多少个索引,MySQL在选择索引时,只考虑在FIELD1和FIELD2上建立的索引限制不使用索引的范围如果我们要考虑的索引很多,而不被使用的索引又很少时,可以使用IGNOREINDEX进行反向选取在上面的例子中是选择被考虑的索引,而使用IGNOREINDEX是选择不被考虑的索引
1.SELECT*FROMTABLE1IGNOREINDEXFIELD1FIELD2…在上面的SQL语句中,TABLE1表中只有FIELD1和FIELD2上的索引不被使用强迫使用某一个索引上面的两个例子都是给MySQL提供一个选择,也就是说MySQL并不一定要使用这些索引而有时我们希望MySQL必须要使用某一个索引由于MySQL在查询时只能使用一个索引,因此只能强迫MySQL使用一个索引这就需要使用FORCEINDEX来完成这个功能
1.SELECT*FROMTABLE1FORCEINDEXFIELD1…以上的SQL语句只使用建立在FIELD1上的索引,而不使用其它字段上的索引
3.使用临时表提供查询性能当我们查询的结果集中的数据比较多时,可以通过SQL_BUFFER_RESULT.选项强制将结果集放到临时表中,这样就可以很快地释放MySQL的表锁这样其它的SQL语句就可以对这些记录进行查询了,并且可以长时间地为客户端提供大记录集
1.SELECTSQL_BUFFER_RESULT*FROMTABLE1WHERE…和SQL_BUFFER_RESULT.选项类似的还有SQL_BIG_RESULT,这个选项一般用于分组或DISTINCT关键字,这个选项通知MySQL,如果有必要,就将查询结果放到临时表中,甚至在临时表中进行排序
1.SELECTSQL_BUFFER_RESULTFIELD1COUNT*FROMTABLE1GROUPBYFIELD
114、MySQL与其他数据库有哪些特点答案MySQL是一个小型关系型数据库管理系统,开发者为瑞典MySQLAB公司,现在已经被Sun公司收购,支持FreeBSD、Linux、MAC、Windows等多种操作系统与其他的大型数据库例如Oracle、DB
2、SQLServer等相比功能稍弱一些
1、可以处理拥有上千万条记录的大型数据
2、支持常见的SQL语句规范
3、可移植行高,安装简单小巧
4、良好的运行效率,有丰富信息的网络支持
5、调试、管理,优化简单(相对其他大型数据库)
15、操作数据库的基本流程答案所有的JDBC应用程序都具有下面的基本流程
1、建立到数据库的连接
2、执行SQL语句
3、处理结果
4、从数据库断开连接 下面我们就来仔细看一看每一个步骤 建立到数据库的连接 通过JDBC使用数据库的第一步就是建立一个连接JDBC连接是由URL指定的,它的格式如下 jdbc:: 其中subprotocol是被请求的数据库连接的类型(如ODBC,ORACLE,Informix等等),而subname提供了所要建立的连接的一些附加信息当JDBC驱动程序管理器收到一个连接的URL时,所有已知的JDBC驱动程序会被询问是否可以为这个URL服务请求一个通过JDBC-ODBC桥到叫做MyData的ODBC数据源的连接的例子如下 Connectioncon=DriverManage.getconnection“jdbc:odbc:MyData”; 看上去一切都很顺利,但是JDBC驱动程序管理器是怎么知道哪些JDBC驱动程序在当前的系统中可用呢?有两种机制可以通知驱动程序管理器一个JDBC驱动程序可以使用sql.drivers属性和JDBC驱动程序注册 驱动程序管理器引用sql.drivers系统属性来取得当前系统中可用的JDBC驱动程序列表这个系统属性包含一些用冒号隔开的JDBC驱动程序的类名,通过这个类名,驱动程序管理器可以试图满足一个连接请求 使用驱动程序注册更为常见这种方法使你对你要使用的JDBC驱动程序有更多的控制所有的JDBC驱动程序在实例化的时候都必须在驱动程序管理器中注册自己,注册可以通过下列两个方法来实现
2.newfoo.Driver; 我个人比较喜欢使用Class.forName这种方法,不过这两种方法的效果是相同的JDBC驱动程序用驱动程序管理器注册自己,这样,它就可以为连接请求服务了 执行SQL语句 在数据库连接成功建立之后,我们就可以执行那些完成实际工作的SQL语句了在执行SQL语句之前,我们必须首先创建一个语句对象,这个对象提供了到特定数据库SQL引擎的接口有下列三种不同类型的语句对象
1.Statement——基本的语句对象,它提供了直接在数据库中执行SQL语句的方法对于那些只执行一次的查询以及DDL语句如CREATETABLE,DROPTABLE等等来说,statement对象就足够了
2.Preparedstatement——这种语句对象用于那些需要执行多次,每次仅仅是数据取值不同的SQL语句,它还提供了一些方法,以便指出语句所使用的输入参数
3.Callablestatement——这种语句对象被用来访问数据库中的存储过程它提供了一些方法来指定语句所使用的输入输出参数 下面是一个用语句类来执行SQLSELECT语句的一个例子 Statementstmt=con.createStatement; ResultSetrs=stmt.executeQuery“SELECT*FROMMyTable”; 处理结果 在执行了一个SQL语句之后,我们必须处理得到的结果有些语句仅仅返回一个整形数,指出受到影响的行数(比如UPDATE和DELETE语句)SQL查询(SELECT语句)返回一个含有查询结果的结果集结果集由行和列组成,各列数据可以通过相应数据库类型的一系列get方法(如getString,getInt,getDate等等)来取得在取得了一行数据的所有数据之后,我们可以调用next方法来移到结果集中的下一条记录JDBC规范的
1.1版只允许forward-onle只向前型的游标,而在JDBC
2.0中有更健壮的游标控制功能,我们可以向后移动游标而且可以将游标移动到指定行 从数据库断开连接 在结果集、语句和连接对象用完以后,我们必须正确地关闭它们连接对象、结果集对象以及所有的语句对象都有close方法,通过调用这个方法,我们可以确保正确释放与特定数据库系统相关的所有资源 有些开发者喜欢将引用乱放,然后用一个垃圾收集程序专门负责正确清除对象我强烈建议大家在使用了JDBC驱动程序之后调用close方法这样可以尽可能的减少由于挂起的对象残留在数据库系统中而造成的内存泄漏。