Reprint! ! ! Eight ways to optimize MySQL database (classic must-see)

1. Select the most applicable field attribute

MySQL can support large data access well, but in general, the smaller the table in the database, the faster the query will be executed on it. Therefore, when creating a table, in order to obtain better performance, we can set the width of the fields in the table as small as possible.

For example, when defining the field of postal code, if it is set to CHAR(255), it obviously adds unnecessary space to the database, and even using VARCHAR is redundant, because CHAR(6) can be very good. Mission accomplished. Also, if possible, we should use MEDIUMINT instead of BIGIN to define integer fields.

Another way to improve efficiency is to set the field to NOTNULL when possible, so that the database does not have to compare NULL values ​​when executing queries in the future. 
For some text fields, such as "province" or "gender", we can define them as ENUM type. Because in MySQL, ENUM types are treated as numeric data, and numeric data is processed much faster than text types. In this way, we can improve the performance of the database again.

2. Use join (JOIN) instead of sub-queries (Sub-Queries)

MySQL supports subqueries in SQL since 4.1. This technique uses a SELECT statement to create a single-column query result, which can then be used as a filter condition in another query. For example, if we want to delete customers who do not have any orders in the customer basic information table, we can use a subquery to first extract all the customer IDs that issued orders from the sales information table, and then pass the results to the main query, as shown below :

DELETEFROMcustomerinfo

WHERECustomerIDNOTin(SELECTCustomerIDFROMsalesinfo)

Using subqueries can complete many SQL operations that logically require multiple steps to complete at one time, and can also avoid transaction or table locking, and it is easy to write. However, in some cases, subqueries can be replaced by more efficient joins (JOINs). For example, suppose we want to fetch all users who have no order records, which can be done with the following query:

SELECT*FROMcustomerinfo

WHERECustomerIDNOTin(SELECTCustomerIDFROMsalesinfo)

If you use join (JOIN) .. to do this query work, it will be much faster. Especially when there is an index on CustomerID in the salesinfo table, the performance will be better. The query is as follows:

SELECT*FROMcustomerinfo

LEFTJOINsalesinfoONcustomerinfo.CustomerID=salesinfo.CustomerID

WHEREsalesinfo.CustomerIDISNULL

JOIN .. is more efficient because MySQL doesn't need to create a temporary table in memory to do this logically two-step query.

3. Use UNION instead of manually created temporary tables

MySQL supports union query since version 4.0, which can combine two or more select queries that need to use temporary tables into one query. At the end of the client's query session, the temporary table will be automatically deleted, so as to ensure that the database is tidy and efficient. When using union to create a query, we only need to use UNION as a keyword to connect multiple select statements. It should be noted that the number of fields in all select statements must be the same. The following example demonstrates a query using UNION.

SELECTName,PhoneFROMclientUNION

SELECTName,BirthDateFROMauthorUNION

SELECTName,SupplierFROMproduct

4. Affairs

尽管我们可以使用子查询(Sub-Queries)、连接(JOIN)和联合(UNION)来创建各种各样的查询,但不是所有的数据库操作都可以只用一条或少数几条SQL语句就可以完成的。更多的时候是需要用到一系列的语句来完成某种工作。但是在这种情况下,当这个语句块中的某一条语句运行出错的时候,整个语句块的操作就会变得不确定起来。设想一下,要把某个数据同时插入两个相关联的表中,可能会出现这样的情况:第一个表中成功更新后,数据库突然出现意外状况,造成第二个表中的操作没有完成,这样,就会造成数据的不完整,甚至会破坏数据库中的数据。要避免这种情况,就应该使用事务,它的作用是:要么语句块中每条语句都操作成功,要么都失败。换句话说,就是可以保持数据库中数据的一致性和完整性。事物以BEGIN关键字开始,COMMIT关键字结束。在这之间的一条SQL操作失败,那么,ROLLBACK命令就可以把数据库恢复到BEGIN开始之前的状态。

BEGIN; INSERTINTOsalesinfoSETCustomerID=14;UPDATEinventorySETQuantity=11WHEREitem=’book’;COMMIT;

事务的另一个重要作用是当多个用户同时使用相同的数据源时,它可以利用锁定数据库的方法来为用户提供一种安全的访问方式,这样可以保证用户的操作不被其它的用户所干扰。

5、锁定表

尽管事务是维护数据库完整性的一个非常好的方法,但却因为它的独占性,有时会影响数据库的性能,尤其是在很大的应用系统中。由于在事务执行的过程中,数据库将会被锁定,因此其它的用户请求只能暂时等待直到该事务结束。如果一个数据库系统只有少数几个用户来使用,事务造成的影响不会成为一个太大的问题;但假设有成千上万的用户同时访问一个数据库系统,例如访问一个电子商务网站,就会产生比较严重的响应延迟。

其实,有些情况下我们可以通过锁定表的方法来获得更好的性能。下面的例子就用锁定表的方法来完成前面一个例子中事务的功能。

LOCKTABLEinventoryWRITESELECTQuantityFROMinventoryWHEREItem=’book’;

UPDATEinventorySETQuantity=11WHEREItem=’book’;UNLOCKTABLES

Here, we use a select statement to fetch the initial data, do some calculations, and update the table with the new values ​​with an update statement. A LOCKTABLE statement that includes the WRITE keyword ensures that no other accesses will be made to insert, update, or delete the inventory until the UNLOCKTABLES command is executed.

6. Use foreign keys

The method of locking the table can maintain the integrity of the data, but it cannot guarantee the associativity of the data. This time we can use foreign keys.

For example, a foreign key can ensure that every sales record points to an existing customer. Here, the foreign key can map the CustomerID in the customerinfo table to the CustomerID in the salesinfo table, and any record without a valid CustomerID will not be updated or inserted into salesinfo.

CREATETABLEcustomerinfo( CustomerIDINTNOTNULL,PRIMARYKEY(CustomerID))TYPE=INNODB;

CREATETABLEsalesinfo( SalesIDINTNOTNULL,CustomerIDINTNOTNULL,

PRIMARYKEY(CustomerID,SalesID),

FOREIGNKEY(CustomerID)REFERENCEScustomerinfo(CustomerID)ONDELETECASCADE)TYPE=INNODB; 
Note the parameter "ONDELETECASCADE" in the example. This parameter ensures that when a customer record in the customerinfo table is deleted, all records related to the customer in the salesinfo table will also be automatically deleted. If you want to use foreign keys in MySQL, you must remember to define the table type as transaction-safe table InnoDB type when you create the table. This type is not the default type for MySQL tables. The way to define it is to add TYPE=INNODB to the CREATETABLE statement. as shown in the example.

7. Use indexes

Indexing is a common way to improve database performance, it allows the database server to retrieve specific rows much faster than without an index, especially when the query contains MAX(), MIN() and ORDERBY commands. The performance improvement is more obvious.

Which fields should be indexed?

In general, indexes should be built on those fields that will be used for JOIN, WHERE and ORDERBY sorting. Try not to index a field in the database that contains a lot of duplicate values. For an ENUM type field, a large number of duplicate values ​​are likely to occur

For example the "province".. field in customerinfo, indexing on such a field will not help; on the contrary, it may also reduce the performance of the database. We can create appropriate indexes at the same time when we create the table, or we can use ALTERTABLE or CREATEINDEX to create indexes later. Additionally, MySQL supports full-text indexing and searching since version 3.23.23. Full-text index is a FULLTEXT type index in MySQL, but can only be used for MyISAM type tables. For a large database, loading the data into a table without a FULLTEXT index and then using ALTERTABLE or CREATEINDEX to create the index will be very fast. But if the data is loaded into a table that already has a FULLTEXT index, the execution process will be very slow.

8. Optimized query statements

绝大多数情况下,使用索引可以提高查询的速度,但如果SQL语句使用不恰当的话,索引将无法发挥它应有的作用。

下面是应该注意的几个方面。

首先,最好是在相同类型的字段间进行比较的操作。

在MySQL3.23版之前,这甚至是一个必须的条件。例如不能将一个建有索引的INT字段和BIGINT字段进行比较;但是作为特殊的情况,在CHAR类型的字段和VARCHAR类型字段的字段大小相同的时候,可以将它们进行比较。

其次,在建有索引的字段上尽量不要使用函数进行操作。

例如,在一个DATE类型的字段上使用YEAE()函数时,将会使索引不能发挥应有的作用。所以,下面的两个查询虽然返回的结果一样,但后者要比前者快得多。

第三,在搜索字符型字段时,我们有时会使用LIKE关键字和通配符,这种做法虽然简单,但却也是以牺牲系统性能为代价的。 
例如下面的查询将会比较表中的每一条记录。

SELECT*FROMbooks

WHEREnamelike”MySQL%” 
但是如果换用下面的查询,返回的结果一样,但速度就要快上很多:

SELECT*FROMbooks

WHEREname>=”MySQL”andname<”MySQM” 

最后,应该注意避免在查询中让MySQL进行自动类型转换,因为转换过程也会使索引变得不起作用。


转载于:

      https://blog.csdn.net/tototuzuoquan/article/details/80089748



Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325810998&siteId=291194637