집 >데이터 베이스 >MySQL 튜토리얼 >MySQL 데이터베이스를 최적화하는 방법
MySQL은 대량의 데이터에 대한 액세스를 잘 지원하지만 일반적으로 데이터베이스의 테이블은 더 작습니다. 즉, 이에 대한 쿼리가 더 빠르게 실행됩니다. 따라서 테이블을 생성할 때 더 나은 성능을 얻기 위해 테이블의 필드 너비를 최대한 작게 설정할 수 있습니다.
예를 들어 우편번호 필드를 정의할 때 CHAR(255)로 설정하면 분명히 데이터베이스에 불필요한 공간이 추가됩니다. CHAR(6)을 사용하면 쉽게 가능하므로 VARCHAR을 사용해도 중복됩니다. 마찬가지로 가능하다면 BIGIN 대신 MEDIUMINT를 사용하여 정수 필드를 정의해야 합니다.
효율성을 높이는 또 다른 방법은 가능할 때마다 필드를 NOTNULL로 설정하여 나중에 쿼리를 실행할 때 데이터베이스가 NULL 값을 비교할 필요가 없도록 하는 것입니다. "지방" 또는 "성별"과 같은 일부 텍스트 필드의 경우 ENUM 유형으로 정의할 수 있습니다. 왜냐하면 MySQL에서는 ENUM 유형이 숫자 데이터로 처리되고, 숫자 데이터는 텍스트 유형보다 훨씬 빠르게 처리되기 때문입니다. 이런 방식으로 데이터베이스의 성능을 향상시킬 수 있습니다.
DELETE FROM customerinfo WHERE CustomerID NOT IN (SELECT CustomerID FROM salesinfo)하위 쿼리를 사용하면 논리적으로 한 번에 여러 단계를 완료해야 하는 많은 SQL 작업을 완료할 수 있으며 트랜잭션 또는 테이블 잠금을 피할 수도 있고 작성하기도 쉽습니다. 그러나 하위 쿼리를 보다 효율적인 조인(JOIN)으로 대체할 수 있는 상황이 있습니다. 예를 들어, 주문 기록이 없는 모든 사용자를 가져오려고 한다고 가정하면 다음 쿼리를 사용하여 이를 완료할 수 있습니다.
SELECT * FROM customerinfo WHERE CustomerID NOT IN (SELECTC ustomerID FROM salesinfo)
연결(JOIN)을 사용하는 경우... 이 쿼리를 완료하려면 속도가 빨라집니다. 훨씬 더 빨라지세요. 특히 salesinfo 테이블에 CustomerID에 대한 인덱스가 있는 경우 쿼리는 다음과 같습니다.
SELECT * FROM customerinfo LEFT JOIN salesinfo ON customerinfo.CustomerID=salesinfo.CustomerID WHERE salesinfo.CustomerID ISNULLJoin(JOIN).. 더 효율적인 이유는 MySQL에서 생성할 필요가 없기 때문입니다. 메모리의 임시 테이블입니다. 이 논리적 쿼리를 완료하려면 두 단계가 필요합니다.
SELECT Name,Phone FROM client UNION SELECT Name,BirthDate FROM author UNION SELECT Name,Supplier FROM product
4. Transactions
서브쿼리(Sub-Queries), 커넥션(JOIN), 유니온(UNION)을 이용하여 다양한 쿼리를 생성할 수 있지만, 모든 데이터베이스 작업이 사용만으로 완료될 수는 없습니다. 하나 또는 몇 개의 SQL 문을 사용합니다. 특정 종류의 작업을 완료하려면 일련의 명령문이 필요한 경우가 더 많습니다. 그러나 이 경우 해당 명령문 블록의 특정 명령문이 잘못 실행되면 전체 명령문 블록의 작동이 불확실해집니다. 두 개의 관련 테이블에 동시에 특정 데이터를 삽입하려고 한다고 가정해 보겠습니다. 첫 번째 테이블이 성공적으로 업데이트된 후 데이터베이스에서 예기치 않은 상황이 발생하여 두 번째 테이블의 작업이 완료되지 않을 수 있습니다. 이런 방식으로 데이터가 불완전해지고 데이터베이스에 있는 데이터도 삭제됩니다. 이러한 상황을 피하려면 트랜잭션을 사용해야 합니다. 해당 기능은 명령문 블록의 모든 명령문이 성공하거나 실패하는 것입니다. 즉, 데이터베이스 내 데이터의 일관성과 무결성을 유지할 수 있습니다. BEGIN 키워드로 시작하여 COMMIT 키워드로 끝납니다. 이 기간 동안 SQL 작업이 실패하면 ROLLBACK 명령은 BEGIN이 시작되기 전의 상태로 데이터베이스를 복원할 수 있습니다.BEGIN; INSERT INTO salesinfo SET CustomerID=14; UPDATE inventory SET Quantity=11 WHERE item='book'; COMMIT;트랜잭션의 또 다른 중요한 역할은 여러 사용자가 동시에 동일한 데이터 소스를 사용할 때 데이터베이스를 잠그는 방법을 사용하여 사용자에게 안전한 액세스 방법을 제공할 수 있다는 것입니다. 이를 통해 사용자의 작업이 방해받지 않도록 할 수 있습니다. 다른 사용자에 의해 차단되었습니다.
尽管事务是维护数据库完整性的一个非常好的方法,但却因为它的独占性,有时会影响数据库的性能,尤其是在很大的应用系统中。由于在事务执行的过程中,数据库将会被锁定,因此其它的用户请求只能暂时等待直到该事务结束。如果一个数据库系统只有少数几个用户来使用,事务造成的影响不会成为一个太大的问题;但假设有成千上万的用户同时访问一个数据库系统,例如访问一个电子商务网站,就会产生比较严重的响应延迟。
其实,有些情况下我们可以通过锁定表的方法来获得更好的性能。下面的例子就用锁定表的方法来完成前面一个例子中事务的功能。
LOCK TABLE inventory WRITE SELECT Quantity FROM inventory WHERE Item='book'; ... UPDATE inventory SET Quantity=11 WHERE Item='book'; UNLOCKTABLES
这里,我们用一个select语句取出初始数据,通过一些计算,用update语句将新值更新到表中。包含有WRITE关键字的LOCKTABLE语句可以保证在UNLOCKTABLES命令被执行之前,不会有其它的访问来对inventory进行插入、更新或者删除的操作。
锁定表的方法可以维护数据的完整性,但是它却不能保证数据的关联性。这个时候我们就可以使用外键。
例如,外键可以保证每一条销售记录都指向某一个存在的客户。在这里,外键可以把customerinfo表中的CustomerID映射到salesinfo表中CustomerID,任何一条没有合法CustomerID的记录都不会被更新或插入到salesinfo中。
CREATE TABLE customerinfo( CustomerIDINT NOT NULL,PRIMARYKEY(CustomerID))TYPE=INNODB; CREATE TABLE salesinfo( SalesIDNT NOT NULL,CustomerIDINT NOT NULL, PRIMARYKEY(CustomerID,SalesID), FOREIGNKEY(CustomerID) REFERENCES customerinfo(CustomerID) ON DELETE CASCADE)TYPE=INNODB;
注意例子中的参数“ON DELETE CASCADE”。该参数保证当customerinfo表中的一条客户记录被删除的时候,salesinfo表中所有与该客户相关的记录也会被自动删除。如果要在MySQL中使用外键,一定要记住在创建表的时候将表的类型定义为事务安全表InnoDB类型。该类型不是MySQL表的默认类型。定义的方法是在CREATETABLE语句中加上TYPE=INNODB。如例中所示。
索引是提高数据库性能的常用方法,它可以令数据库服务器以比没有索引快得多的速度检索特定的行,尤其是在查询语句当中包含有MAX(),MIN()和ORDERBY这些命令的时候,性能提高更为明显。
那该对哪些字段建立索引呢?
一般说来,索引应建立在那些将用于JOIN,WHERE判断和ORDERBY排序的字段上。尽量不要对数据库中某个含有大量重复的值的字段建立索引。对于一个ENUM类型的字段来说,出现大量重复值是很有可能的情况
例如customerinfo中的“province”..字段,在这样的字段上建立索引将不会有什么帮助;相反,还有可能降低数据库的性能。我们在创建表的时候可以同时创建合适的索引,也可以使用ALTERTABLE或CREATEINDEX在以后创建索引。此外,MySQL从版本3.23.23开始支持全文索引和搜索。全文索引在MySQL中是一个FULLTEXT类型索引,但仅能用于MyISAM类型的表。对于一个大的数据库,将数据装载到一个没有FULLTEXT索引的表中,然后再使用ALTERTABLE或CREATEINDEX创建索引,将是非常快的。但如果将数据装载到一个已经有FULLTEXT索引的表中,执行过程将会非常慢。
绝大多数情况下,使用索引可以提高查询的速度,但如果SQL语句使用不恰当的话,索引将无法发挥它应有的作用。
下面是应该注意的几个方面。
首先,最好是在相同类型的字段间进行比较的操作。
在MySQL3.23版之前,这甚至是一个必须的条件。例如不能将一个建有索引的INT字段和BIGINT字段进行比较;但是作为特殊的情况,在CHAR类型的字段和VARCHAR类型字段的字段大小相同的时候,可以将它们进行比较。
其次,在建有索引的字段上尽量不要使用函数进行操作。
例如,在一个DATE类型的字段上使用YEAE()函数时,将会使索引不能发挥应有的作用。所以,下面的两个查询虽然返回的结果一样,但后者要比前者快得多。
例如下面的查询将会比较表中的每一条记录。
SELECT * FROM books WHERE name like"MySQL%"
但是如果换用下面的查询,返回的结果一样,但速度就要快上很多:
SELECT * FROM books WHERE name>="MySQL" andname <"MySQM"
最后,应该注意避免在查询中让MySQL进行自动类型转换,因为转换过程也会使索引变得不起作用。
위 내용은 MySQL 데이터베이스를 최적화하는 방법의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!