PHP+MariaDB数据库操作基本技巧备忘总结

本文实例总结了PHP+MariaDB数据库操作基本技巧。分享给大家供大家参考,具体如下:

PHP+MysqL是比较常见的搭配,由于我主观上不太喜欢Oracle,而MysqL被它收购后,骨子里也发生了一些变化,因此我更换了MariaDB,仍然坚持MysqL当初开源信念的亲兄弟。本质上都是MysqL的内核,因此下面所有的数据库操作代码,都是可以直接在MysqL使用的。

晚上搭好PHP+Apache的基础环境,以及安装好MysqL数据库后,写了一个最简单的数据库连接代码,结果报了如下经典错误Fatal error: Class 'MysqLi' not found

rush:PHP;"> PHP $db = new MysqLi('localhost','root','admin','test'); if (MysqLi_connect_errno()) { echo '

' . 'Connect DB error'; exit; } ?>

其实这问题比较简单,从PHP引擎返回的错误就知道MysqLi没有被正确的加载,绝大多数的问题都发生在PHP.ini文件的配置中,“PHP_MysqLi.dll”这个配置项前面认的分号没有去掉。这个错误我倒没有犯,PHP安装路径中的ext目录中,也有PHP_MysqLi.dll这个文件,那问题发生在哪里呢?问题应该还是发生在PHP.ini文件中哪个地方写错了。走读后发现“修改。我当时脑子没多想,觉得PHP引擎是能够自动找到这个相对路径的。但后来想想,PHP引擎是被Apache加载的,Apache可不知道这个相对关系。还是老老实实的把这个地方改成了绝对路径,OK了。其实可以在这代码之前,先写这么一段代码,看看MysqLi组件是否已经被加载了,这个方法适用于其他组件的加载前的判断。

rush:PHP;"> if (extension_loaded('MysqLi')) { echo 'yes'; } else { echo 'no'; }

下面用一个用户注册和系统登录记录PHP+MysqL的最基本操作方法

1、创建数据库、表和用户

rush:sql;"> DROP DATABASE IF EXISTS `test`; CREATE DATABASE `test` USE `test`; DROP TABLE IF EXISTS `tbl_user`; CREATE TABLE `tbl_user` ( `username` varchar(32) NOT NULL default '',`password` varchar(32) NOT NULL default '',PRIMARY KEY (`username`) ) ENGINE=InnoDB DEFAULT CHARSET=gb2312;

2、创建注册登录的html页面,分别是register.html和login.html。如下图所示:

3、注册登录代码

register_do.PHP

rush:PHP;"> PHP $username = $_POST['username']; $password = $_POST['password']; $db = new MysqLi('localhost','test'); if (MysqLi_connect_errno()) { echo '

' . 'Connect DB error'; exit; } $query = "select * from tbl_user where username = '" . $username . "'"; echo '

' . $query; $result = $db->query($query); if ($result) { echo '

' . 'The user '. $username .' exist'; echo '

' . 'Back to register'; } else { $query = "insert into tbl_user values ('". $username ."','". $password ."')"; echo '

' . $query; $result = $db->query($query); if ($result) { echo '

' . 'Register successful'; } } ?>

login_do.PHP

rush:PHP;"> PHP $username = $_POST['username']; $password = $_POST['password']; $db = new MysqLi('localhost','test'); if (MysqLi_connect_errno()) { echo '

' . 'Connect DB error'; exit; } $query = "select * from tbl_user where username = '" . $username . "' and password = '" . $password . "'"; echo '

' . $query; $result = $db->query($query); if ($result->num_rows) { echo '

' . 'Login successful'; } else { echo '

' . 'Login failed'; } ?>

userlist.PHP

rush:PHP;"> PHP $db = new MysqLi('localhost','test'); if (MysqLi_connect_errno()) { echo '

' . 'Connect DB error'; exit; } echo '

' . 'All user as follows:'; $query = "select * from tbl_user order by username"; if ($result = $db->query($query)) { while ($row = $result->fetch_assoc()) { echo '

' . 'Username : ' . $row['username'] . ' delete'; } } ?>

4、该页面最终的显示效果如下图所示:

5、删除用户代码

userdelete.PHP

rush:PHP;"> PHP $username = $_GET['username']; $db = new MysqLi('localhost','test'); if (MysqLi_connect_errno()) { echo '

' . 'Connect DB error'; exit; } $query = "delete from tbl_user where username = '" . $username . "'"; echo $query; if ($result = $db->query($query)) { echo '

' . 'Delete user ' . $username . ' successful'; } else { echo '

' . 'Delete user ' . $username . ' Failed'; } echo '

' . 'Back to user list'; ?>

Prepare预处理

1、图书添加页面如下图所示(bookadd.html):

2、建表脚本如下:

rush:sql;"> DROP DATABASE IF EXISTS `test`; CREATE DATABASE IF NOT EXISTS `test`; USE `test`; DROP TABLE IF EXISTS `tbl_book`; CREATE TABLE IF NOT EXISTS `tbl_book` ( `isbn` varchar(32) NOT NULL,`title` varchar(32) NOT NULL,`author` varchar(32) NOT NULL,`price` float NOT NULL,PRIMARY KEY (`isbn`) ) ENGINE=InnoDB DEFAULT CHARSET=utf-8;

3、添加的逻辑处理代码如下(bookadd_do.PHP):这里特别要注意的是这句话“$db->query("set names utf-8")”,代表向数据库写入数据时,采用utf-8编解码,显示的对数据库表操作的编解码进行设置,以防止中文的乱码。后面我会专门针对这个技术点记录一篇文章

rush:PHP;"> PHP $isbn = $_POST['isbn']; $title = $_POST['title']; $author = $_POST['author']; $price = $_POST['price']; $db = new MysqLi('localhost','test'); if (MysqLi_connect_errno()) { echo '

' . 'Connect DB error'; exit; } $db->query("set names utf-8"); //特别注意这句话 $stmt = $db->stmt_init(); $stmt->prepare("insert into tbl_book values (?,?,?)"); $stmt->bind_param("sssd",$isbn,$title,$author,$price); $stmt->execute(); echo '

' . 'Affect rows is ' . $stmt->affected_rows; echo '

' . 'Go to book list page'; ?>

4、显示图书信息的逻辑代码如下,同样注意这句话“$db->query("set names utf-8")”:

rush:PHP;"> PHP $db = new MysqLi('localhost','test'); if (MysqLi_connect_errno()) { echo '

' . 'Connect DB error'; exit; } $db->query("set names utf-8"); //特别注意这句话 $stmt = $db->stmt_init(); $stmt->prepare("select * from tbl_book"); $stmt->bind_result($isbn,$price); $stmt->execute(); while($stmt->fetch()) { echo 'ISBN : ' . $isbn . '

'; echo 'Title : ' . $title . '

'; echo 'Author : ' . $author . '

'; echo 'Price : ' . $price . '

'; echo '

' . '-----------------------------' . '

'; } ?>

5、显示页面如下图所示:

好了,最基础的部分就记录到这,PHP引擎提供了很方便的数据库操作方法,但正是开发绝不是如此简单,各种异常要仔细考虑如何捕获,如何处理。数据库的设计也是一个挺好玩的话题。

更多关于PHP相关内容感兴趣的读者可查看本站专题:《》、《》、《》、《》、《》、《》及《PHP常见数据库操作技巧汇总》

希望本文所述对大家PHP程序设计有所帮助。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


安装开始...1.打开“https://dev.mysql.com/downloadsepo/yum/”下载Mysql源      将下载好的mysql源上传linux服务器 2.yumlocalinstallmysql80*#安装源 centos7中默认安装的是mariadb数据库,如果想要安装mysql,首先要移除mariadb;
安装Helm3#官网下载慢#wgethttps://get.helm.sh/helm-v3.5.4-linux-amd64.tar.gzwgethttp://qiniu.dev-share.top/helm-v3.5.4-linux-amd64.tar.gztar-zxvfhelm-v3.5.4-linux-amd64.tar.gzcplinux-amd64/helm/usr/local/bin#查看helmclient版本helmversion
通过Linux命令行启动用的指令:systemctlstartmariadb.service反馈:Failedtostartmariadb.service:Unitmariadb.servicenotfound.MariaDB简介MariaDB是MySQL的一个分支,MariaDB打算保持与MySQL的高度兼容性,确保具有库二进制奇偶校验的直接替换功能,以及与MySQLAPI和命令
InstallingMariaDBServer10.4TodeployMariaDBCommunityServer10.4onRHEL7orCentOS7,firstdownloadandusethe mariadb_repo_setup scripttoconfiguretheMariaDBrepositoriesforYUM:$sudoyuminstallwget$wgethttps://downloads.mariadb.com/
首先我们来回顾下代理的概念,所谓代理就是指的是一端面向客户端,另外一端面向服务端,代理客户端访问服务端,我们把这种代理叫正向代理;代理服务端响应客户端我们叫做反向代理,这个我们在之前nginx系列博客
mariadb的主从复制集群,默认情况下是把主库上的所有库进行复制,只要在主库上产生写操作,从库基于主库的二进制日志做重放,从而实现把主库的上的库表复制到从库;复制过滤器指的是我们仅复制一个或几个数据
首先我们来了解下在mariadb/mysql数据库主从复制集群中什么是同步,什么是异步,什么是半同步;所谓同步就是指主节点发生写操作事件,它不会立刻返回,而是等到从节点接收到主节点发送过来的写操作事件
首先我们来看看mariadb的锁定概念,所谓锁就是当一个进程或事务在操作某一资源时,为了防止其他用户或者进程或事务对其进行资源操作,导致资源抢占而发生冲突,通常在A进程操作该资源时,会对该资源进行加锁
前面我们聊到了mariadb的事务,以及事务隔离级别,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13198186.html;今天我们来聊一聊mariadb的
上一篇我们聊到了mariadb的锁,以及怎么手动加锁和解锁等等,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13196905.html;今天我们来聊一聊mar
一、xtrabackup 简介 xtrabackup 是由percona公司开源免费的数据库热备软件,它能对InnoDB数据库和XtraDB存储引擎的数据库非阻塞地备份,对于myisam的备份同样需要
1、 导入hellodb.sql生成数据库 [root@test-centos7-node1 ~]# rz rz waiting to receive. zmodem trlʼ ȡ 100
1、编写脚本,支持让用户自主选择,使用mysqldump还是xtraback全量备份。 [root@test-centos7-node1 scripts]# cat chose_backup_mysq
问题描述vagrant@homestead:~/Code/zookeeper-3.4.9/bin$ sudo mysql -uroot -p Enter password:ERROR 1045 (28000): Access denied for user 'r
## 1 安装Mariadb > 使用默认的 `yum install mariadb-server`时,默认安装的是和Mysql相兼容的5.5版本。想要安装更高的版本,必须先指定yum源。 ### 1.1 使用源配置向导 [配置向导](https://downloads.mariadb.org/mariadb/repositories): https://downloads.mariadb.org/mariadb/repositories 可以选择合适的操作系统...
xtrabackup备份(MySQL备份)与恢复1. innobackupex参数选项--no-timestamp: 不创建一个时间戳--defaults-file=[MY.CNF] //指定配置文件:只能从给定的文件中读取默认选项。 且必须作为命令行上的第一个选项;必须是一个真实的文件,它不能是一个符号链接。--databases=# //指定备份的数据库和表,格式为:--database="db1[.tb1] db2[.tb2]" 多个库之间以空格隔开,如果此选项不被指定,将会备份所有的数据库。--include=REGEXP //用正则表达式的方式指定要备份的数据库和表,格式为 --include=‘^mydb[.]mytb’ ,对每个库中的每个表逐一匹配,因此会创建所有的库,不过是空的目录。--include 传递给 xtrabackup --tables。--tables-file=FILE //此选项的参数需要是一个文件名,此文件中每行包含一个要备份的表的完整名称,格式为databasename.tablename。该选项传递给 xtrabackup --tables-file,与--tables选项不同,只有要备份的表的库才会被创建。注意:部分备份(--include、--tables-file、--database)需要开启 innodb_file_per_table 。--compact //创建紧凑型备份,忽略所有辅助索引页,只备份data page;通过--apply-log中重建索引--rebuild-indexs。--compress //此选项指示xtrabackup压缩备份的InnoDB数据文件,会生成 *.qp 文件。--apply-log //应用 BACKUP-DIR 中的 xtrabackup_logfile 事务日志文件。一般情况下,在备份完成后,数据尚且不能用于恢复操作,因为备份的数据中可能会包含尚未提交的事务或已经提交但尚未同步至数据文件中的事务。因此,此时数据文件仍处于不一致状态。“准备”的主要作用正是通过回滚未提交的事务及同步已经提交的事务至数据文件使得数据文件处于一致性状态。--use-memory=# //此选项接受一个字符参数(1M/1MB,1G/1GB,默认100M),仅与--apply-log一起使用,该选项指定prepare时用于崩溃恢复(crash-recovery)的内存。--copy-back //拷贝先前备份所有文件到它们的原始路径。但原路径下不能有任何文件或目录,除非指定 --force-non-empty-directories 选项。--incremental-basedir=DIRECTORY //该选项接受一个字符串参数,该参数指定作为增量备份的基本数据集的完整备份目录。它与 --incremental 一起使用。--incremental-dir=DIRECTORY //该选项接受一个字符串参数,该参数指定了增量备份将与完整备份相结合的目录,以便进行新的完整备份。它与 --incremental 选项一起使用。--redo-only //在“准备基本完整备份” 和 “合并所有的增量备份(除了最后一个增备)”时使用此选项。它直接传递给xtrabackup的 xtrabackup --apply-log-only 选项,使xtrabackup跳过"undo"阶段,只做"redo"操作。如果后面还有增量备份应用到这个全备,这是必要的。有关详细信息,请参阅xtrabackup文档。--parallel=NUMBER-OF-THREADS //此选项接受一个整数参数,指定xtrabackup子进程应用于同时备份文件的线程数。请注意,此选项仅适用于文件级别,也就是说,如果您有多个.ibd文件,则它们将被并行复制; 如果您的表一起存储在一个表空间文件中,它将不起作用。2.全量备份恢复创建备份恢复的用户并赋权create user pxb@'localhost' identified by '123456';grant reload,process,lock tables,replication client on . to pxb@localhost;创建存放备份文件的目录mkdir -pv /var/data进行数据库全量备份:innobackupex --defaults-file=/etc/my.cnf --user=pxb --password=123456 /var/data/[root@aliy ~]# ll /var/data/2018-08-28_09-06-39/total 18460-rw-r----- 1 root root 417 Aug 28 09:06 backup-my.cnf-rw-r----- 1 root root 18874368 Aug 28 09:06 ibdata1drwxr-x--- 2 root root 4096 Aug 28 09:06 mysqldrwxr-x--- 2 root root 4096 Aug 28 09:06 performance_schemadrwxr-x--- 2 root root 4096 Aug 28 09:06 test-rw-r----- 1 root root 113 Aug 28 09:06 xtrabackup_checkpoints-rw-r----- 1 root root 454 Aug 28 09:06 xtrabackup_info-rw-r----- 1 root root 2560 Aug 28 09:06 xtrabackup_logfile全量备份恢复systemctl stop mariadbrm /var/lib/mysql -rfmkdir /var/lib/mysql准备一个完全备份: --apply-log,执行之后 xtrabackup_checkpoints 文件中的 backup_type = full-preparedinnobackupex --apply-log /var/data/2018-08-28_09-06-39/执行恢复操作:innobackupex --defaults-file=/etc/my.cnf --copy-back /var/data/2018-08-28_09-06-39/更改data目录权限并启动mysql:chown -R mysql:mysql /var/lib/mysqlsystemctl start mariadb3. 增量备份恢复所谓增量备份恢复就是在全量的基础上进行增量备份。增量备份1:以全量为基准innobackupex --defaults-file=/etc/my.cnf --user=pxb --password=123456 --incremental /var/data/inc --incremental-basedir=/var/data/2018-08-28_10-01-53/ --parallel=2中途进行了数据添加操作。增量备份2:以增量备份1为基准innobackupex --defaults-file=/etc/my.cnf --user=pxb --password=123456 --incremental /var/data/inc/ --incremental-basedir=/var/data/inc/2018-08-28_10-04-22/ --parallel=2增量备份的恢复:步骤:恢复完全备份恢复增量备份到完全备份(开始恢复的增量备份要添加--redo-only参数,到最后一次增量备份要去掉--redo-only)对整体的完全备份进行恢复,回滚提交的数据准备一个全备:innobackupex --apply-log --redo-only /var/data/2018-08-28_10-01-53/将增量1应用到完全备份innobackupex --apply-log --redo-only /var/data/2018-08-28_10-01-53 --incremental-dir=/var/data/inc/2018-08-28_10-04-22/将增量2应用到完全备份,不用加--redo-only参数innobackupex --apply-log /var/data/2018-08-28_10-01-53 --incremental-dir=/var/data/inc/2018-08-28_10-07-40/把所有的完全备份合并到一起进行一次apply操作,回滚提交的数据innobackupex --apply-log /var/data/2018-08-28_10-01-53/模拟:将数据库里的内容删除systemctl stop mariadbmv /var/lib/mysql /var/lib/mysql.bakmkdir /var/lib/mysql恢复:innobackupex --defaults-file=/etc/my.cnf --copy-back /var/data/2018-08-28_10-01-53/chown -R mysql:mysql /var/lib/mysqlsystemctl start maraidb流备份以及压缩备份Xtrabackup对备份的数据文件支持“流”功能,即可以将备份的数据通过STDOUT传输给tar程序进行归档,而不是默认的直接保存至某备份目录中。要使用此功能,仅需要使用--stream选项即可。如:innobackupex --stream=tar /data/backup/|gzip >/data/backup/`date +%F`.tar.gz也可以使用如下命令将数据备份至其他服务器innobackupex --default-file=/etc/my.cnf --stream=tar /backup | ssh user@www.magedu.com " cat -> /backups/date +%F_%H-%M-%S.tar"同时也可将备份的数据文件存储到远程的主机,使用--remote-host来实现innobackupex --remote-host=root@www.magedu.com /path/IN/REMOTE/HOST/to/backup
停止mysql服务在mysql配置文件里[mysqld]下添加skip-grant-tables3.重启服务,进入mysql4.修改密码:MariaDB [mysql]> update mysql.user set password=PASSWORD('123456') where User='root';MariaDB [(none)]> flush privileges;成功后,退出,注释掉刚才的配置文件,重启服务。
原文:http://www.ibm.com/developerworks/library/os-beyondmysql/IntroductionMySQL is one of the most popular free and open source programs in history. It's the database backbone for thousands of websites and could arguably be given credit (along with Linux®) for the explosive growth of the Internet over the past 10 years.So, if MySQL is so important, why is increasing amount of high profile off-shoots of the core MySQL product? Because MySQL is free and open source, developers have always been able to take the code, modify it as they see fit, and distribute it on their own. For a long time, there weren't any branches of MySQL that a developer would trust in their own production environment. However, that's changing rapidly. Several branches are getting a lot of attention.This article will discuss three popular branches of MySQL that are gaining attention: Drizzle, MariaDB, and Percona Server, including the XtraDB engine. This article will talk briefly about the reasons for each branch and their goals, and whether to use them in your own production environment. By the time you finish this article, you should be able to answer the question "Are these MySQL branch products a good solution for my environment?"Why branch?Why does MySQL need to be branched? That's a very legitimate question. Thousands of websites depend on it and it seems to be a good solution for many people. However, as is often the case, what's good for many people isn't good for all people. Some developers are motivated to make things better for their own needs. What could be better than turning a great solution into the perfect solution?Let's get into more specific details about what these branches sought to change. Some branches felt that MySQL was becoming too bloated and was offering many features that would never interest users, at the expense of simplicity of performance. If people were perfectly happy with the more streamlined MySQL 4, why should they deal with the additional complexity that was added with MySQL 5? For this branch, a preferred branch of MySQL would be simpler and faster — offer less features, but make them extremely quick, keeping in mind a target audience, in this case high availability websites.To other branches, MySQL wasn't offering enough new features, or were adding them too slowly. They may have felt that MySQL wasn't keeping up with its target markets of high availability websites running on multi-core processors with lots of RAM. As people familiar with MySQL know, it offers two different storage enginges — MyISAM and InnoDB. This branch felt that neither of these storage engines offered them exactly what they were looking for, so they created a new storage engine perfectly suited for their goals.Further, some branches have a top goal to be a "drop in" replacement to MySQL, where you could simply drop in their branch and not have to change one line of code. The branch uses the same code and interfaces as MySQL, making a transition as easy as possible. Yet, another branch boasts that it's not compatible with MySQL, requiring code changes. Each branch is also at a different maturity level, with some claiming they are production ready, and some claiming they are far from that goal at this point.Finally, there's uncertainty about how MySQL will fare under Oracle. Oracle bought Sun, who bought MySQL, and right now Oracle controls the MySQL product itself, and leads the development community in producing new finished products. Because Oracle already has a commercial database, there is concern that they may not put sufficient resources into MySQL to keep it cutting-edge. Therefore, many branches are also a result of the underlying fear that MySQL, the leading free and open source database, may see less features, slower release cycles, and more expensive support.XtraDBXtraDB is not a stand-alone product itself, but it is still considered a branch of MySQL. XtraDB is actually a storage engine for MySQL-based databases. This would be considered an additional storage engine to the standard MyISAM and InnoDB that are already a part of MySQL. MySQL 4 and 5 installs with each table using the default MyISAM storage engine. InnoDB is also a relatively newer option for a storage engine, and database administrators and developers can choose the types of storage engine, on a per table basis, when they set up the database. The major difference between the two storage engines is that MyISAM does not offer transactional support, while InnoDB does. Other differences are many small performance differences, with InnoDB offering many small performance improvements over MyISAM, and more reliability and safety when dealing with potential data loss. As it appears that InnoDB is the better-suited storage engine for future improvements, MySQL has switched the default storage engine to InnoDB instead of MyISAM starting with the 5.5 release.Building on these advantages, the InnoDB storage engine itself has been branched into a newer storage engine called XtraDB. Just how new is this storage engine? It was
原文地址:http://mysql.rjweb.org/doc.php/ricksrotsBrought to you by Rick JamesHere are 160+ tips, tricks, suggestions, etc. They come from a decade of improving performance in MySQL in thousands of situations. There are exceptions to the statements below, but they should help guide you into better understanding how to effectively use MySQL. SELECTs -- do's and don'tsRoTsDiscussion    ⚈  Do not hide an indexed column inside a function call: DATE(x) = '...', LCASE(col) = 'foo'     ⚈  LCASE() is usually unnecessary because the collation will compare 'correctly' without it.     ⚈  #1: Subqueries perform poorly     ⚈  Never use "IN (SELECT...)" -- optimizes poorly. Turn into JOIN. (5.6.5 improves)     ⚈  A subquery that condenses data (GROUP BY, LIMIT, etc) may perform well     ⚈  OR may be very inefficient; turn into UNION.     ⚈  A coding pattern: dt >= '2010-02-01' AND dt < '2010-02-01' + INTERVAL 7 DAY     ⚈  ORDER BY NULL -- a little-known trick to avoid GROUP BY doing a sort (if there is another way).     ⚈  WHERE (a,b) > (7,8) is poorly optimized     ⚈  Gather these to study a slow query: SHOW CREATE TABLE, SHOW TABLE STATUS, EXPLAIN.     ⚈  Do not use OFFSET for pagination -- continue where you "left off"     ⚈  Don't mix DISTINCT and GROUP BY     ⚈  Be explicit about UNION ALL vs UNION DISTINCT -- it makes you think about which to use     ⚈  Do not use SELECT * except for debugging or when fetching into a hash.     ⚈  VIEWs are poorly optimized     ⚈  A subquery in the FROM clause may be useful for retrieving BLOBs without sorting them: Speed up a query by first finding the IDs, then self-JOIN to fetch the rest. Subqueries came to MySQL rather late in the game. They have not been well optimized, so it is usually better to turn your SELECTs into an equivalent JOIN. This is especially true for "IN ( SELECT ... )", but that is better optimized in 5.6.5 and MariaDB 5.5. Sometimes a subquery is really the best way to optimize a SELECT. The common thread of these "good" subqueries seems to be when the subquery has to scan a lot of rows, but boils down the intermediate resultset to a small number of rows. This is likely to happen with GROUP BY or LIMIT in the subquery. Index hints (FORCE INDEX, etc) may help you today, but may be the wrong thing for tomorrow -- different constants in the WHERE clause may lead FORCE to do the "wrong" thing. For analyzing a slow query, SHOW CREATE TABLE provides the datatypes, indexes, and engine. (DESCRIBE provides much less info.) SHOW TABLE STATUS tells how big the table is. EXPLAIN says how the query optimizer decided to perform the query. It is so tempting to use ORDER BY id LIMIT 30,10to find the 4th page of 10 items. But it is so inefficient, especially when you have thousands of pages. The thousandth page has to read (at some level) all the pages before it. "Left off" refers to having the "Next" button on one page give the id (or other sequencing info) of where the next page can be found. Then that page simply does WHERE id > $leftoff ORDER BY id LIMIT 10. More on pagination.INDEXingRoTsDiscussion    ⚈  #1: Start an INDEX with "="s from the WHERE clause, then one other thing (range, group, order)     ⚈  Terms: PRIMARY KEY > UNIQUE > INDEX = KEY     ⚈  An index _may_ speed up a SELECT by orders of magnitude and will slow down INSERTs a little. (A fair tradeoff?)     ⚈  Adding indexes is not a panacea.     ⚈  BTree is an excellent all-around indexing mechanism     ⚈  A BTree index node contains ~100 items. (1M rows = 3 levels; 1B rows = 5 levels)     ⚈  Flags, and other fields with few values, should not be alone in an index -- the index won't be used.     ⚈  MySQL rarely uses two INDEXes in one SELECT. Main exceptions: subqueries, UNION.     ⚈  A "prefix" index -- INDEX(name(10)) -- is rarely useful. Exception: TEXT     ⚈  A UNIQUE "prefix" is probably wrong -- UNIQUE(name(10)) forces 10 chars to be unique.     ⚈  It is ok to have Index_length > Data_length     ⚈  5 fields in a compound index seems "too many"     ⚈  Having no compound indexes is a clue that you do not understand their power. INDEX(a,b) may be much better than INDEX(a), INDEX(b)     ⚈  INDEX(a,b) covers for INDEX(a), so drop the latter.     ⚈  2x speedup when "Using index" (a "covering" index)     ⚈  Akiban (3rd party) "groups" tables together, interleaved, to improve JOIN performance.     ⚈  FULLTEXT (MyISAM) -- watch out for ft_min_word_len=4, stopwords, and 50% rule     ⚈  A FULLTEXT index will be used before any other index.     ⚈  FULLTEXT -- consider Syphinx, Lucene, etc (3rd Party) Indexing is very important to any database. Getting the "right" index can make a query run orders of magnitude faster. So, how to do that? Often "compound indexes" (multiple columns in a single INDEX(...)) are better than single-column indexes. A WHERE clause that has column=constant begs for an index that starts with that column. If the WHERE
http://www.infoq.com/cn/articles/in-mysql-never-use-utf8-use-utf8最近我遇到了一个bug,我试着通过Rails在以“utf8”编码的MariaDB中保存一个UTF-8字符串,然后出现了一个离奇的错误:Incorrect string value: ‘xF0x9Fx98x83 <…’ for column ‘summary’ at row 1我用的是UTF-8编码的客户端,服务器也是UTF-8编码的,数据库也是,就连要保存的这个字符串“ <…”也是合法的UTF-8。问题的症结在于,MySQL的“utf8”实际上不是真正的UTF-8。“utf8”只支持每个字符最多三个字节,而真正的UTF-8是每个字符最多四个字节。MySQL一直没有修复这个bug,他们在2010年发布了一个叫作“utf8mb4”的字符集,绕过了这个问题。 当然,他们并没有对新的字符集广而告之(可能是因为这个bug让他们觉得很尴尬),以致于现在网络上仍然在建议开发者使用“utf8”,但这些建议都是错误的。简单概括如下:MySQL的“utf8mb4”是真正的“UTF-8”。MySQL的“utf8”是一种“专属的编码”,它能够编码的Unicode字符并不多。我要在这里澄清一下:所有在使用“utf8”的MySQL和MariaDB用户都应该改用“utf8mb4”,永远都不要再使用“utf8”。那么什么是编码?什么是UTF-8?我们都知道,计算机使用0和1来存储文本。比如字符“C”被存成“01000011”,那么计算机在显示这个字符时需要经过两个步骤:计算机读取“01000011”,得到数字67,因为67被编码成“01000011”。计算机在Unicode字符集中查找67,找到了“C”。同样的:我的电脑将“C”映射成Unicode字符集中的67。我的电脑将67编码成“01000011”,并发送给Web服务器。几乎所有的网络应用都使用了Unicode字符集,因为没有理由使用其他字符集。Unicode字符集包含了上百万个字符。最简单的编码是UTF-32,每个字符使用32位。这样做最简单,因为一直以来,计算机将32位视为数字,而计算机最在行的就是处理数字。但问题是,这样太浪费空间了。UTF-8可以节省空间,在UTF-8中,字符“C”只需要8位,一些不常用的字符,比如“”需要32位。其他的字符可能使用16位或24位。一篇类似本文这样的文章,如果使用UTF-8编码,占用的空间只有UTF-32的四分之一左右。MySQL的“utf8”字符集与其他程序不兼容,它所谓的“”,可能真的是一坨……MySQL简史为什么MySQL开发者会让“utf8”失效?我们或许可以从提交日志中寻找答案。MySQL从4.1版本开始支持UTF-8,也就是2003年,而今天使用的UTF-8标准(RFC 3629)是随后才出现的。旧版的UTF-8标准(RFC 2279)最多支持每个字符6个字节。2002年3月28日,MySQL开发者在第一个MySQL 4.1预览版中使用了RFC 2279。同年9月,他们对MySQL源代码进行了一次调整:“UTF8现在最多只支持3个字节的序列”。是谁提交了这些代码?他为什么要这样做?这个问题不得而知。在迁移到Git后(MySQL最开始使用的是BitKeeper),MySQL代码库中的很多提交者的名字都丢失了。2003年9月的邮件列表中也找不到可以解释这一变更的线索。不过我可以试着猜测一下。2002年,MySQL做出了一个决定:如果用户可以保证数据表的每一行都使用相同的字节数,那么MySQL就可以在性能方面来一个大提升。为此,用户需要将文本列定义为“CHAR”,每个“CHAR”列总是拥有相同数量的字符。如果插入的字符少于定义的数量,MySQL就会在后面填充空格,如果插入的字符超过了定义的数量,后面超出部分会被截断。MySQL开发者在最开始尝试UTF-8时使用了每个字符6个字节,CHAR(1)使用6个字节,CHAR(2)使用12个字节,并以此类推。应该说,他们最初的行为才是正确的,可惜这一版本一直没有发布。但是文档上却这么写了,而且广为流传,所有了解UTF-8的人都认同文档里写的东西。不过很显然,MySQL开发者或厂商担心会有用户做这两件事:使用CHAR定义列(在现在看来,CHAR已经是老古董了,但在那时,在MySQL中使用CHAR会更快,不过从2005年以后就不是这样子了)。将CHAR列的编码设置为“utf8”。我的猜测是MySQL开发者本来想帮助那些希望在空间和速度上双赢的用户,但他们搞砸了“utf8”编码。所以结果就是没有赢家。那些希望在空间和速度上双赢的用户,当他们在使用“utf8”的CHAR列时,实际上使用的空间比预期的更大,速度也比预期的慢。而想要正确性的用户,当他们使用“utf8”编码时,却无法保存像“”这样的字符。在这个不合法的字符集发布了之后,MySQL就无法修复它,因为这样需要要求所有用户重新构建他们的数据库。最终,MySQL在2010年重新发布了“utf8mb4”来支持真正的UTF-8。为什么这件事情会让人如此抓狂因为这个问题,我整整抓狂了一个礼拜。我被“utf8”愚弄了,花了很多时间才找到这个bug。但我一定不是唯一的一个,网络上几乎所有的文章都把“utf8”当成是真正的UTF-8。“utf8”只能算是个专有的字符集,它给我们带来了新问题,却一直没有得到解决。总结如果你在使用MySQL或MariaDB,不要用“utf8”编码,改用“utf8mb4”。这里(https://mathiasbynens.be/notes/mysql-utf8mb4#utf8-to-utf8mb4)提供了一个指南用于将现有数据库的字符编码从“utf8”转成“utf8mb4”。英文原文:https://medium.com/@adamhooper/in-mysql-never-use-utf8-use-utf8mb4-11761243e434