网上也找了很多方案结果就是奇葩的不成功,最后直接修改/etc/mysql/mysql.conf.d/mysqld.cnf成功了。 在该文件最后添加
default-storage-engine=INNODB character-set-server=utf8 collation-server=utf8_general_ci 重启成功。
这是本地虚拟机里的mysql
mysql> show variables like "character%"; +--------------------------+----------------------------+ | Variable_name | Value | +--------------------------+----------------------------+ | character_set_client | utf8 | | character_set_connection | utf8 | | character_set_database | utf8 | | character_set_filesystem | binary | | character_set_results | utf8 | | character_set_server | utf8 | | character_set_system | utf8 | | character_sets_dir | /usr/share/mysql/charsets/ | +--------------------------+----------------------------+ 完全正确,但是修改阿里云服务器以后还是有点小问题
character_set_database这一项还是latin1,不过似乎并不影响。 友情提示:纠正了mysql字符集发现新建的表还是latin1字符集,那有可能是该数据库本身的字符集就不对,可以试着看看。
由于开发物流信息网,关于这个问题也是最近才想到的,就是到底读文件更快还是读数据库更快,能快多少,书生也搜索过,没见有网友就这个问题答复过, 也可能是太简单的缘故,我们本文还是来实测一下,由于时间关系,VC还没装,书生先用PHP测试了一下,下次有时间在C/C++上补充测试到本文来,因为 PHP的底层解析应该也是基于C的,所以估计两者环境测试结果差不多,小问题大收获,现在就来看一下测试过程及结果。
测试程序如下: //说明1:由于读数据库语句调用简单的封包函数两次,所以把读文件也改成连续调用两次,数据库记录ID为1就在第一条,并且唯一索引。
//说明2:测试两次一次是4K数据,一次是整形数据
set_time_limit(0); function fnGet($filename) { $content = file_get_contents($filename); return $content; } function fnGetContent($filename) { $content = fnGet($filename); return $content; } $times=100000; echo '数据库查询结果:<br/>'; //--------------------------------- $begin=fnGetMicroTime(); for($i=0;$i<$times;$i++) { $res=$dbcon->mydb_query("SELECT log_Content FROM blog WHERE log_ID='1'"); $row=$dbcon->mydb_fetch_row($res); $content=$row[0]; } echo 'fetch_row '.$times.' 次时间:<font color=red>'.(fnGetMicroTime()-$begin).'</font>秒<br/>'; //--------------------------------- $begin=fnGetMicroTime(); for($i=0;$i<$times;$i++) { $res=$dbcon->mydb_query("SELECT log_Content FROM blog WHERE log_ID='1'"); $row=$dbcon->mydb_fetch_array($res); $content=$row['log_Content']; } echo 'fetch_array '.$times.' 次时间:<font color=red>'.(fnGetMicroTime()-$begin).'</font>秒<br/>'; //--------------------------------- $begin=fnGetMicroTime(); for($i=0;$i<$times;$i++) { $res=$dbcon->mydb_query("SELECT log_Content FROM blog WHERE log_ID='1'"); $row=$dbcon->mydb_fetch_object($res); $content=$row->log_Content; } echo 'fetch_object '.
数据库优化第一想到的应该是建立索引,而且是最快速有效的优化方式,一般是对where子句中的字段建立索引,但是并不是越多越好,对于基数(区分度)越大的效果越好,比如唯一索引。对于一些表示状态的,比如值为0,1这类区分状态的字段就算数据再多索引的基数也很小,这类字段并不是非要加索引,加的索引越多越占磁盘空间,每次写入数据都要更新大量索引,反而成为累赘。但是不要以为真的没必要加,初学者对索引的认识浅薄,要么不加索引,要么在建表时就妄自推断加了很多索引。那么如何加索引才是正确的做法呢?
数据库中有一种是单列索引,一种是多列索引,要怎么加需要搞清楚这两者的区别,当查询条件有多个字段时,单列索引和多列索引有很大的区别。
如果使用多列索引,where条件中字段的顺序非常重要,需要满足最左前缀列。
最左前缀:查询条件中的所有字段需要从左边起按顺序出现在多列索引中,查询条件的字段数要小于等于多列索引的字段数,中间字段不能存在范围查询的字段(<,like等),这样的sql可以使用该多列索引。
mysql多列索引适合的场景
全字段匹配 匹配部分最左前缀 匹配第一列 匹配第一列范围查询(可用用like a%,但不能使用like %b) 精确匹配某一列和和范围匹配另外一列 order by操作中出现的字段同样适用于按值查找的规则,where+order by中出现的字段需可以建立满足如上五种规则多列索引。 使用多列需要按照最左索引列查找;不能跳过中间列;如果某一列是范围查询,那么其右边所有列无法使用索引。 IN什么情况下是范围查询,什么情况下是多个等值查询?如果有order by排序时,多个等于条件查询就是范围查询,没有order by排序就没有限制。 例如,建立多列索引(name, age, id), 只能使用索引的前两列。in是范围查询 … where name=“nginx.cn” and age in(15,16,17) order by id 可以使用整个索引,in是按值查询 … where name=“nginx.cn” and age in(15,16,17) and id =“3”
以前找工作的时候总被面试到数据库方面的知识,尤其是数据库优化。当然在去面试之前先补习一下,背一些网上的概念来应付。现在想想,要考察一个开发者数据库优化方面的知识只需要问一下有没有做过数据库设计和优化就行,如果做过相关工作那么多少会总结出来一些,如果没做过说出再多也是概念而已。
国庆节前韩豆咖派上线,然后这个节日就不会有好日子过了,上线三四天的时候很多用户反映帖子刷新不出来,登陆不了等问题,起初我以为是放假了大家回家网络不好导致的,后来测试了下接口花了一分多钟数据才返回,看来不是网络问题。查了下数据库帖子数量,居然达到6万了,想到以前背的概念,首先加索引试试,果然快了。但是节后数量达到12万的时候又出现了相同的问题,有点纳闷,索引页加了怎么还是慢呢?经过多次试验,分拆复杂查询后得出结论是由于查询语句中使用了left join自连接查询,通俗的说就是在12万数据中找出需要的数据,然后再在这12万中找出关联数据,光是这两个12万都够吓人了。最后还是把复杂的sql分解用程序控制查询子句,速度果然又提高了。
得出结论,一句复杂的sql不一定是最好的,分解成多句简单的sql可能有质的飞跃。这个方案在《高性能MYSQL》一书中也提到了,补充个图片:
但是对于sql查询到底该一次复杂查询还是多次简单查询没有明显界限,只有当一条复杂查询发现很慢的时候再分析慢的原因多次试验后就能知道哪个是最好的,而且复杂的sql也不利于优化,可能加了索引都没用,也不能使用查询缓存。当一条复杂的sql需要花3秒钟才能查出来的时候分拆的简单sql可能每秒可以查询5000次了.
今天是
SELECT NOW();-- 2015-09-28 13:48:12 查询当天,格式为YYYY-MM-DD
SELECT CURDATE();-- 2015-09-28
查询当天,格式为YYYY-MM-DD HH:mm:ss
SELECT NOW();-- 2015-09-28 13:42:00
查询当天0点,格式为YYYY-MM-DD HH:mm:ss
SELECT DATE_FORMAT(CURDATE(),"%Y-%m-%d %H:%i:%s");-- 2015-09-28 00:00:00
查询当天早上9点,格式为YYYY-MM-DD HH:mm:ss
SELECT DATE_ADD(CURDATE(), INTERVAL 9 HOUR);-- 2015-09-28 09:00:00
查询昨天,格式为YYYY-MM-DD
SELECT DATE_SUB(CURDATE(),INTERVAL 1 DAY);-- 2015-09-27
查询昨天早上9点
SELECT DATE_ADD(DATE_SUB(CURDATE(),INTERVAL 1 DAY),INTERVAL 9 HOUR);-- 2015-09-27 09:00:00
DATE_ADD(date,INTERVAL expr type) 参数是合法的日期表达式。expr 参数是您希望增加的时间。
type 参数可以是下列值:
Type 值
MICROSECOND
SECOND
MINUTE
HOUR
DAY
WEEK
MONTH
QUARTER
YEAR
SECOND_MICROSECOND
MINUTE_MICROSECOND
MINUTE_SECOND
HOUR_MICROSECOND
HOUR_SECOND
HOUR_MINUTE
表中有两个日期字段createDate,updateDate。其中updateDate可以为空,要求使用updateDate排序,如果updateDate为空则使用createDate排序,结果要顺序排下来。
按照常规方法:
select * from table order by updateDate desc;
这样的结果是为空的数据排在了最下面,不符合要求。
这样试试:
select * from table order by updateDate desc, createDate desc;
这样排的结果是先按updateDate排序,updateDate为空的排在最下面,然后按createDate排序,这样也不符合要求。
正确方法:
select * from table order by IFNULL(updateDate, createDate) desc;
这种排序的结果是正确的,用ifnull函数判断updateDate如果为空的话就使用createDate排。