your programing

MyISAM 대 InnoDB

lovepro 2020. 9. 28. 09:50
반응형

MyISAM 대 InnoDB


나는 많은 데이터베이스 쓰기를 포함하는 프로젝트에서 일하고 있습니다 ( 70 % 삽입 및 30 % 읽기 ). 이 비율에는 내가 하나의 읽기와 하나의 쓰기로 간주하는 업데이트도 포함됩니다. 읽기가 더러울 수 있습니다 (예 : 읽을 때 100 % 정확한 정보가 필요하지 않음).
문제의 작업은 시간당 100 만 개 이상의 데이터베이스 트랜잭션을 수행합니다.

웹에서 MyISAM과 InnoDB의 차이점에 대해 많은 것을 읽었으며 MyISAM은이 작업에 사용할 특정 데이터베이스 / 테이블에 대한 확실한 선택 인 것 같습니다. 내가 읽은 것처럼 InnoDB는 행 수준 잠금이 지원되므로 트랜잭션이 필요한 경우 좋습니다.

누구든지 이러한 유형의 부하 (또는 그 이상)에 대한 경험이 있습니까? MyISAM이가는 길입니까?


InnoDB 또는 MyISAM 중 어느 쪽을 사용할지 결론을 내릴 수 있도록 표에서이 질문에 대해 간략하게 설명 했습니다 .

다음은 어떤 상황에서 사용해야하는 DB 스토리지 엔진에 대한 간략한 개요입니다.

                                                 MyISAM InnoDB
-------------------------------------------------- --------------
필수 전체 텍스트 검색 예 5.6.4
-------------------------------------------------- --------------
거래 필요 예
-------------------------------------------------- --------------
빈번한 선택 쿼리 예      
-------------------------------------------------- --------------
빈번한 삽입, 업데이트, 삭제 예
-------------------------------------------------- --------------
행 잠금 (단일 테이블에서 다중 처리) 예
-------------------------------------------------- --------------
관계형 기본 설계 예

요약:

잦은 읽기, 거의 쓰기 없음 => MyISAM
MySQL <= 5.5 => MyISAM에서 전체 텍스트 검색

다른 모든 상황에서는 일반적으로 InnoDB 가 가장 좋은 방법입니다.


저는 데이터베이스 전문가가 아니며 경험으로도 말하지 않습니다. 하나:

MyISAM 테이블은 테이블 수준 잠금을 사용합니다 . 예상 트래픽에 따르면 초당 200 회에 가까운 쓰기가 있습니다. MyISAM을 사용하면 언제든지이 중 하나만 진행할 수 있습니다 . 오버런을 방지하기 위해 하드웨어가 이러한 트랜잭션을 따라갈 수 있는지 확인해야합니다. 즉, 단일 쿼리에 5ms를 넘지 않아야합니다.

이는 행 수준 잠금을 지원하는 스토리지 엔진, 즉 InnoDB가 필요하다는 것을 의미합니다.

반면에 각 스토리지 엔진의로드를 시뮬레이션하는 몇 가지 간단한 스크립트를 작성하고 결과를 비교하는 것은 매우 간단합니다.


사람들은 종종 성능, 읽기 대 쓰기, 외래 키 등에 대해 이야기하지만 제 생각에는 스토리지 엔진에 꼭 필요한 기능이 하나 더 있습니다. 바로 원자 적 업데이트입니다.

이 시도:

  1. 5 초가 소요되는 MyISAM 테이블에 대해 UPDATE를 발행하십시오.
  2. 업데이트가 진행되는 동안 2.5 초 후에 Ctrl-C를 눌러 중단합니다.
  3. 테이블에 미치는 영향을 관찰하십시오. 얼마나 많은 행이 업데이트 되었습니까? 얼마나 많이 업데이트되지 않았습니까? 테이블을 읽을 수 있습니까, 아니면 Ctrl-C를 눌렀을 때 손상 되었습니까?
  4. InnoDB 테이블에 대해 UPDATE로 동일한 실험을 시도하여 진행중인 쿼리를 중단합니다.
  5. InnoDB 테이블을 관찰하십시오. 0 개의 행이 업데이트되었습니다. InnoDB는 원 자성 업데이트가 있음을 확인했으며 전체 업데이트를 커밋 할 수없는 경우 전체 변경 사항을 롤백합니다. 또한 테이블이 손상되지 않았습니다. 이것은 killall -9 mysqld충돌을 시뮬레이션하는 데 사용 하는 경우에도 작동합니다 .

물론 성능은 바람직하지만 데이터 손실이 없어야합니다.


MySQL을 사용하여 대용량 시스템에서 작업했으며 MyISAM과 InnoDB를 모두 사용해 보았습니다.

MyISAM의 테이블 수준 잠금으로 인해 작업 부하에 심각한 성능 문제가 발생하는 것으로 나타났습니다. 불행히도 InnoDB에서의 성능도 내가 기대했던 것보다 나쁘다는 것을 발견했습니다.

결국 나는 삽입이 "핫"테이블에 들어가고 핫 테이블을 쿼리하지 않은 선택을 선택하도록 데이터를 조각화하여 경합 문제를 해결했습니다.

이것은 또한 삭제 (데이터는 시간에 민감했고 우리는 단지 X 일 가치를 유지했습니다)가 선택 쿼리에 의해 다시 건드리지 않은 "오래된"테이블에서 발생하는 것을 허용했습니다. InnoDB는 대량 삭제시 성능이 좋지 않은 것으로 보이므로 데이터를 제거 할 계획이라면 이전 데이터가 삭제를 실행하는 대신 간단히 삭제할 수있는 오래된 테이블에 있도록 구조화 할 수 있습니다.

물론 귀하의 응용 프로그램이 무엇인지는 모르겠지만 이것이 MyISAM 및 InnoDB의 일부 문제에 대한 통찰력을 제공하기를 바랍니다.


게임에 조금 늦었지만 여기 에 MYISAM과 InnoDB의 주요 차이점을 자세히 설명 하는 몇 달 전에 작성한 꽤 포괄적 인 게시물이 있습니다. cuppa (그리고 아마도 비스킷)를 잡고 즐기십시오.


MyISAM과 InnoDB의 주요 차이점은 참조 무결성과 트랜잭션에 있습니다. 잠금, 롤백 및 전체 텍스트 검색과 같은 다른 차이점도 있습니다.

참조 무결성

참조 무결성은 테이블 간의 관계가 일관되게 유지되도록합니다. 더 구체적으로 말하자면, 테이블 (예 : 목록)에 다른 테이블 (예 : 제품)을 가리키는 외래 키 (예 : 제품 ID)가있을 때 가리키는 테이블에 업데이트 또는 삭제가 발생하면 이러한 변경 사항이 연결에 계단식으로 적용됨을 의미합니다. 표. 이 예에서 제품 이름이 변경되면 연결 테이블의 외래 키도 업데이트됩니다. '제품'테이블에서 제품이 삭제되면 삭제 된 항목을 가리키는 모든 목록도 삭제됩니다. 또한 모든 새 목록에는 유효한 기존 항목을 가리키는 외래 키가 있어야합니다.

InnoDB는 관계형 DBMS (RDBMS)이므로 참조 무결성이있는 반면 MyISAM은 그렇지 않습니다.

거래 및 원 자성

테이블의 데이터는 SELECT, INSERT, UPDATE 및 DELETE와 같은 DML (Data Manipulation Language) 문을 사용하여 관리됩니다. 트랜잭션은 둘 이상의 DML 문을 단일 작업 단위로 그룹화하므로 전체 단위가 적용되거나 적용되지 않습니다.

MyISAM은 트랜잭션을 지원하지 않지만 InnoDB는 지원합니다.

MyISAM 테이블을 사용하는 동안 작업이 중단되면 작업이 즉시 중단되고 작업이 완료되지 않은 경우에도 영향을받는 행 (또는 각 행 내의 데이터)은 영향을받습니다.

InnoDB 테이블을 사용하는 동안 작업이 중단되면 원 자성이있는 트랜잭션을 사용하므로 커밋이 수행되지 않으므로 완료되지 않은 트랜잭션은 적용되지 않습니다.

테이블 잠금 vs 행 잠금

MyISAM 테이블에 대해 쿼리를 실행하면 쿼리중인 전체 테이블이 잠 깁니다. 즉, 후속 쿼리는 현재 쿼리가 완료된 후에 만 ​​실행됩니다. 큰 테이블을 읽는 중이거나 읽기 및 쓰기 작업이 자주 발생하는 경우 이는 엄청난 쿼리 백 로그를 의미 할 수 있습니다.

InnoDB 테이블에 대해 쿼리가 실행되면 관련된 행만 잠기고 나머지 테이블은 CRUD 작업에 계속 사용할 수 있습니다. 즉, 쿼리가 동일한 행을 사용하지 않는 경우 동일한 테이블에서 동시에 실행할 수 있습니다.

InnoDB의이 기능을 동시성이라고합니다. 동시성만큼이나 선택 범위의 테이블에 적용되는 주요 단점이 있습니다. 커널 스레드 간 전환시 오버 헤드가 있으며 서버가 중단되지 않도록 커널 스레드에 제한을 설정해야합니다. .

트랜잭션 및 롤백

MyISAM에서 작업을 실행하면 변경 사항이 설정됩니다. InnoDB에서는 이러한 변경 사항을 롤백 할 수 있습니다. 트랜잭션을 제어하는 ​​데 사용되는 가장 일반적인 명령은 COMMIT, ROLLBACK 및 SAVEPOINT입니다. 1. COMMIT-여러 DML 작업을 작성할 수 있지만 변경 사항은 COMMIT가 수행 될 때만 저장됩니다. 2. ROLLBACK-아직 커밋되지 않은 작업을 삭제할 수 있습니다. 3. SAVEPOINT-목록에 포인트를 설정합니다. ROLLBACK 작업이 롤백 할 수있는 작업

신뢰할 수 있음

MyISAM은 데이터 무결성을 제공하지 않습니다. 하드웨어 장애, 부정확 한 종료 및 취소 된 작업으로 인해 데이터가 손상 될 수 있습니다. 이를 위해서는 인덱스 및 테이블의 전체 복구 또는 재 구축이 필요합니다.

반면 InnoDB는 트랜잭션 로그, 이중 쓰기 버퍼 및 자동 체크섬 및 유효성 검사를 사용하여 손상을 방지합니다. InnoDB는 변경하기 전에 트랜잭션 이전의 데이터를 ibdata1이라는 시스템 테이블 스페이스 파일에 기록합니다. 충돌이 발생하면 InnoDB는 해당 로그 재생을 통해 자동 복구됩니다.

FULLTEXT 인덱싱

InnoDB는 MySQL 버전 5.6.4까지 FULLTEXT 인덱싱을 지원하지 않습니다. 이 게시물을 작성하는 현재 많은 공유 호스팅 제공 업체의 MySQL 버전이 여전히 5.6.4 미만이므로 InnoDB 테이블에 대해 FULLTEXT 인덱싱이 지원되지 않습니다.

그러나 이것은 MyISAM을 사용하는 유효한 이유가 아닙니다. MySQL의 최신 버전을 지원하는 호스팅 제공 업체로 변경하는 것이 가장 좋습니다. FULLTEXT 인덱싱을 사용하는 MyISAM 테이블은 InnoDB 테이블로 변환 할 수 없습니다.

결론

결론적으로 InnoDB는 기본 스토리지 엔진이어야합니다. 특정 요구 사항을 충족하는 경우 MyISAM 또는 기타 데이터 유형을 선택하십시오.


쓰기 및 읽기가 더 많은로드의 경우 InnoDB의 이점을 누릴 수 있습니다. InnoDB는 테이블 잠금이 아닌 행 잠금을 제공하기 때문에 SELECTs는 서로뿐만 아니라 여러 INSERTs 와도 동시에 발생할 수 있습니다 . 그러나 SQL 트랜잭션을 사용하지 않으려는 경우 InnoDB 커밋 플러시를 2 ( innodb_flush_log_at_trx_commit )로 설정하십시오. 이렇게하면 MyISAM에서 InnoDB로 테이블을 이동할 때 잃을 수있는 많은 원시 성능을 되 찾을 수 있습니다.

또한 복제 추가를 고려하십시오. 이렇게하면 약간의 읽기 확장이 가능하며 읽기가 최신 상태 일 필요는 없다고 말 했으므로 복제가 약간 뒤처지게 할 수 있습니다. 교통량이 가장 많은 곳을 제외하고는 어떤 곳에서도 따라 잡을 수 있는지 확인하십시오. 그러나 이런 식으로 진행하는 경우 슬레이브 및 복제 지연 관리에서 데이터베이스 처리기로 읽기를 분리 하는 것이 좋습니다. 애플리케이션 코드가 이에 대해 알지 못하면 훨씬 간단합니다.

마지막으로, 다양한 테이블로드에 유의하십시오. 모든 테이블에서 읽기 / 쓰기 비율이 동일하지는 않습니다. 거의 100 % 읽기가 가능한 일부 작은 테이블은 MyISAM을 유지할 수 있습니다. 마찬가지로 쓰기가 거의 100 %에 가까운 테이블이 INSERT DELAYED있는 경우을 (를) 유용하게 사용할 수 있지만 MyISAM에서만 지원됩니다 ( DELAYEDInnoDB 테이블 에서는이 절이 무시 됨).

하지만 벤치 마크는 확실합니다.


여기에 두 엔진의 기계적 차이를 포함하는 다양한 응답을 추가하기 위해 경험적 속도 비교 연구를 제시합니다.

순수한 속도 측면에서 MyISAM이 InnoDB보다 항상 빠른 것은 아니지만 내 경험상 PURE READ 작업 환경에서는 약 2.0-2.5 배 더 빠른 경향이 있습니다. 분명히 이것은 모든 환경에 적합하지 않습니다. 다른 사람들이 작성한 것처럼 MyISAM에는 트랜잭션 및 외래 키와 같은 것이 없습니다.

아래에서 약간의 벤치마킹을 수행했습니다. 루프에는 파이썬을 사용하고 타이밍 비교에는 timeit 라이브러리를 사용했습니다. 흥미를 위해 메모리 엔진도 포함 시켰는데, 이것은 작은 테이블에만 적합하지만 전반적으로 최고의 성능을 제공합니다 ( The table 'tbl' is fullMySQL 메모리 제한을 초과 할 때 지속적으로 발생 합니다). 내가 살펴본 네 가지 유형의 선택은 다음과 같습니다.

  1. 바닐라 SELECT
  2. 카운트
  3. 조건부 SELECT
  4. 인덱싱 및 인덱싱되지 않은 하위 선택

먼저 다음 SQL을 사용하여 세 개의 테이블을 만들었습니다.

CREATE TABLE
    data_interrogation.test_table_myisam
    (
        index_col BIGINT NOT NULL AUTO_INCREMENT,
        value1 DOUBLE,
        value2 DOUBLE,
        value3 DOUBLE,
        value4 DOUBLE,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8

두 번째 및 세 번째 테이블에서 'InnoDB'와 '메모리'를 'MyISAM'으로 대체했습니다.

 

1) 바닐라 선택

질문: SELECT * FROM tbl WHERE index_col = xx

결과 : 무승부

다른 데이터베이스 엔진에 의한 바닐라 선택 비교

이들의 속도는 모두 대체로 동일하며 예상대로 선택할 열 수에서 선형입니다. InnoDB는 MyISAM보다 약간 빠르지 만 실제로는 한계가 있습니다.

암호:

import timeit
import MySQLdb
import MySQLdb.cursors
import random
from random import randint

db = MySQLdb.connect(host="...", user="...", passwd="...", db="...", cursorclass=MySQLdb.cursors.DictCursor)
cur = db.cursor()

lengthOfTable = 100000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)
    cur.execute(insertString3)

db.commit()

# Define a function to pull a certain number of records from these tables
def selectRandomRecords(testTable,numberOfRecords):

    for x in xrange(numberOfRecords):
        rand1 = randint(0,lengthOfTable)

        selectString = "SELECT * FROM " + testTable + " WHERE index_col = " + str(rand1)
        cur.execute(selectString)

setupString = "from __main__ import selectRandomRecords"

# Test time taken using timeit
myisam_times = []
innodb_times = []
memory_times = []

for theLength in [3,10,30,100,300,1000,3000,10000]:

    innodb_times.append( timeit.timeit('selectRandomRecords("test_table_innodb",' + str(theLength) + ')', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('selectRandomRecords("test_table_myisam",' + str(theLength) + ')', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('selectRandomRecords("test_table_memory",' + str(theLength) + ')', number=100, setup=setupString) )

 

2) 카운트

질문: SELECT count(*) FROM tbl

결과 : MyISAM이 승리

서로 다른 데이터베이스 엔진 별 개수 비교

이것은 MyISAM과 InnoDB의 큰 차이를 보여줍니다. MyISAM (및 메모리)은 테이블의 레코드 수를 추적하므로이 트랜잭션은 빠르고 O (1)입니다. InnoDB가 계산하는 데 필요한 시간은 내가 조사한 범위의 테이블 크기에 따라 매우 선형 적으로 증가합니다. 실제로 관찰되는 MyISAM 쿼리의 많은 속도 향상은 유사한 효과 때문이라고 생각합니다.

암호:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to count the records
def countRecords(testTable):

    selectString = "SELECT count(*) FROM " + testTable
    cur.execute(selectString)

setupString = "from __main__ import countRecords"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('countRecords("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('countRecords("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('countRecords("test_table_memory")', number=100, setup=setupString) )

 

3) 조건부 선택

질문: SELECT * FROM tbl WHERE value1<0.5 AND value2<0.5 AND value3<0.5 AND value4<0.5

결과 : MyISAM이 승리

다른 데이터베이스 엔진에 의한 조건부 선택 비교

여기서 MyISAM과 메모리는 거의 동일한 성능을 발휘하며 더 큰 테이블의 경우 InnoDB를 약 50 % 능가합니다. 이것은 MyISAM의 이점이 극대화되는 것처럼 보이는 일종의 쿼리입니다.

암호:

myisam_times = []
innodb_times = []
memory_times = []

# Define a function to perform conditional selects
def conditionalSelect(testTable):
    selectString = "SELECT * FROM " + testTable + " WHERE value1 < 0.5 AND value2 < 0.5 AND value3 < 0.5 AND value4 < 0.5"
    cur.execute(selectString)

setupString = "from __main__ import conditionalSelect"

# Truncate the tables and re-fill with a set amount of data
for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE test_table_innodb"
    truncateString2 = "TRUNCATE test_table_myisam"
    truncateString3 = "TRUNCATE test_table_memory"

    cur.execute(truncateString)
    cur.execute(truncateString2)
    cur.execute(truncateString3)

    for x in xrange(theLength):
        rand1 = random.random()
        rand2 = random.random()
        rand3 = random.random()
        rand4 = random.random()

        insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
        insertString3 = "INSERT INTO test_table_memory (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)
        cur.execute(insertString3)

    db.commit()

    # Count and time the query
    innodb_times.append( timeit.timeit('conditionalSelect("test_table_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('conditionalSelect("test_table_myisam")', number=100, setup=setupString) )
    memory_times.append( timeit.timeit('conditionalSelect("test_table_memory")', number=100, setup=setupString) )

 

4) 하위 선택

결과 : InnoDB가 승리

이 쿼리의 경우 하위 선택에 대한 추가 테이블 집합을 만들었습니다. 각각은 BIGINT의 두 열로, 하나는 기본 키 인덱스가 있고 다른 하나는 인덱스가 없습니다. 테이블 크기가 크기 때문에 메모리 엔진을 테스트하지 않았습니다. SQL 테이블 생성 명령은 다음과 같습니다.

CREATE TABLE
    subselect_myisam
    (
        index_col bigint NOT NULL,
        non_index_col bigint,
        PRIMARY KEY (index_col)
    )
    ENGINE=MyISAM DEFAULT CHARSET=utf8;

다시 한 번 두 번째 테이블에서 'MyISAM'이 'InnoDB'로 대체됩니다.

이 쿼리에서는 선택 테이블의 크기를 1000000으로두고 대신 하위 선택 열의 크기를 변경합니다.

다른 데이터베이스 엔진에 의한 하위 선택 비교

여기서 InnoDB는 쉽게 승리합니다. 합리적인 크기 테이블에 도달하면 두 엔진 모두 하위 선택의 크기에 따라 선형으로 확장됩니다. 인덱스는 MyISAM 명령의 속도를 높이지만 흥미롭게도 InnoDB 속도에는 거의 영향을 미치지 않습니다. subSelect.png

암호:

myisam_times = []
innodb_times = []
myisam_times_2 = []
innodb_times_2 = []

def subSelectRecordsIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString = "from __main__ import subSelectRecordsIndexed"

def subSelectRecordsNotIndexed(testTable,testSubSelect):
    selectString = "SELECT * FROM " + testTable + " WHERE index_col in ( SELECT non_index_col FROM " + testSubSelect + " )"
    cur.execute(selectString)

setupString2 = "from __main__ import subSelectRecordsNotIndexed"

# Truncate the old tables, and re-fill with 1000000 records
truncateString = "TRUNCATE test_table_innodb"
truncateString2 = "TRUNCATE test_table_myisam"

cur.execute(truncateString)
cur.execute(truncateString2)

lengthOfTable = 1000000

# Fill up the tables with random data
for x in xrange(lengthOfTable):
    rand1 = random.random()
    rand2 = random.random()
    rand3 = random.random()
    rand4 = random.random()

    insertString = "INSERT INTO test_table_innodb (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"
    insertString2 = "INSERT INTO test_table_myisam (value1,value2,value3,value4) VALUES (" + str(rand1) + "," + str(rand2) + "," + str(rand3) + "," + str(rand4) + ")"

    cur.execute(insertString)
    cur.execute(insertString2)

for theLength in [3,10,30,100,300,1000,3000,10000,30000,100000]:

    truncateString = "TRUNCATE subselect_innodb"
    truncateString2 = "TRUNCATE subselect_myisam"

    cur.execute(truncateString)
    cur.execute(truncateString2)

    # For each length, empty the table and re-fill it with random data
    rand_sample = sorted(random.sample(xrange(lengthOfTable), theLength))
    rand_sample_2 = random.sample(xrange(lengthOfTable), theLength)

    for (the_value_1,the_value_2) in zip(rand_sample,rand_sample_2):
        insertString = "INSERT INTO subselect_innodb (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"
        insertString2 = "INSERT INTO subselect_myisam (index_col,non_index_col) VALUES (" + str(the_value_1) + "," + str(the_value_2) + ")"

        cur.execute(insertString)
        cur.execute(insertString2)

    db.commit()

    # Finally, time the queries
    innodb_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString) )
    myisam_times.append( timeit.timeit('subSelectRecordsIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString) )

    innodb_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_innodb","subselect_innodb")', number=100, setup=setupString2) )
    myisam_times_2.append( timeit.timeit('subSelectRecordsNotIndexed("test_table_myisam","subselect_myisam")', number=100, setup=setupString2) )

나는이 모든 것에 대한 집으로 가져가는 메시지는 당신이 정말로 속도에 대해 염려 한다면 어떤 엔진이 더 적합한 지에 대한 가정을하기보다는 당신이하고있는 쿼리를 벤치마킹해야한다는 것입니다.


주제에서 약간 벗어 났지만 문서화 및 완전성을 위해 다음을 추가하고 싶습니다.

일반적으로 InnoDB를 사용하면 응용 프로그램이 훨씬 덜 복잡해지며 버그가 없을 수도 있습니다. 모든 참조 무결성 (Foreign Key-constraints)을 데이터 모델에 넣을 수 있기 때문에 MyISAM에 필요한만큼의 애플리케이션 코드가 거의 필요하지 않습니다.

기록을 삽입, 삭제 또는 교체 할 때마다 관계를 확인하고 유지해야합니다. 예를 들어 부모를 삭제하면 모든 자식도 삭제되어야합니다. 예를 들어, 단순한 블로깅 시스템에서도 블로그 게시 기록을 삭제하면 댓글 기록, 좋아요 등을 삭제해야합니다. InnoDB에서는 데이터베이스 엔진에서 자동으로 수행됩니다 (모델에 제약 조건을 지정한 경우). )이며 애플리케이션 코드가 필요하지 않습니다. MyISAM에서 이것은 웹 서버에서 매우 어려운 응용 프로그램에 코딩되어야합니다. 웹 서버는 본질적으로 매우 동시 적 / 병렬 적이며 이러한 작업은 원자 적이어야하고 MyISAM은 실제 트랜잭션을 지원하지 않기 때문에 웹 서버에 MyISAM을 사용하는 것은 위험하고 오류가 발생하기 쉽습니다.

또한 대부분의 일반적인 경우 InnoDB는 여러 가지 이유로 훨씬 더 나은 성능을 발휘합니다. 하나는 테이블 수준 잠금과는 반대로 레코드 수준 잠금을 사용할 수 있다는 것입니다. 쓰기가 읽기보다 더 빈번한 상황뿐만 아니라 대규모 데이터 세트에 대한 복잡한 조인이있는 상황에서도 마찬가지입니다. 매우 큰 조인 (몇 분 소요)을 위해 MyISAM 테이블보다 InnoDB 테이블을 사용하는 것만으로도 3 배의 성능 향상을 발견했습니다.

일반적으로 InnoDB (참조 무결성을 갖춘 3NF 데이터 모델 사용)는 MySQL을 사용할 때 기본 선택이되어야합니다. MyISAM은 매우 특정한 경우에만 사용해야합니다. 성능이 떨어지고 응용 프로그램이 더 크고 버그가 많을 것입니다.

이것을 말한 것. 데이터 모델링은 웹 디자이너 / 프로그래머 사이에서 거의 발견되지 않는 예술입니다. 위반은 아니지만 MyISAM이 너무 많이 사용되는 것을 설명합니다.


InnoDB는 다음을 제공합니다.

ACID transactions
row-level locking
foreign key constraints
automatic crash recovery
table compression (read/write)
spatial data types (no spatial indexes)

InnoDB에서 TEXT 및 BLOB를 제외한 행의 모든 ​​데이터는 최대 8,000 바이트를 차지할 수 있습니다. InnoDB에는 전체 텍스트 인덱싱을 사용할 수 없습니다. InnoDB에서 COUNT (*) s (WHERE, GROUP BY 또는 JOIN이 사용되지 않은 경우)는 행 수가 내부적으로 저장되지 않기 때문에 MyISAM에서보다 느리게 실행됩니다. InnoDB는 데이터와 인덱스를 하나의 파일에 저장합니다. InnoDB는 버퍼 풀을 사용하여 데이터와 인덱스를 모두 캐시합니다.

MyISAM은 다음을 제공합니다.

fast COUNT(*)s (when WHERE, GROUP BY, or JOIN is not used)
full text indexing
smaller disk footprint
very high table compression (read only)
spatial data types and indexes (R-tree)

MyISAM에는 테이블 수준 잠금이 있지만 행 수준 잠금은 없습니다. 거래가 없습니다. 자동 크래시 복구는 없지만 복구 테이블 기능을 제공합니다. 외래 키 제약이 없습니다. MyISAM 테이블은 일반적으로 InnoDB 테이블과 비교할 때 디스크 크기가 더 작습니다. MyISAM 테이블은 필요한 경우 myisampack으로 압축하여 크기를 더욱 크게 줄일 수 있지만 읽기 전용이됩니다. MyISAM은 인덱스를 한 파일에 저장하고 데이터를 다른 파일에 저장합니다. MyISAM은 인덱스 캐싱을 위해 키 버퍼를 사용하고 데이터 캐싱 관리를 운영 체제에 맡깁니다.

전반적으로 나는 대부분의 용도로 InnoDB를, 특수 용도로만 MyISAM을 권장합니다. InnoDB는 이제 새로운 MySQL 버전의 기본 엔진입니다.


당신의 MyISAM을 사용하는 경우, 당신은 일을하지 않습니다 어떤 당신은 (어떤 경우에, 충돌의 경우에 내구성이나 원자되지 않습니다) 거래를 할 각 DML 문을 고려하지 않는 한, 시간당 트랜잭션을.

따라서 InnoDB를 사용해야한다고 생각합니다.

초당 300 건의 트랜잭션은 상당히 많은 것 같습니다. 정전시에도 이러한 트랜잭션이 지속되어야하는 경우 I / O 하위 시스템이 초당이 많은 쓰기를 쉽게 처리 할 수 ​​있는지 확인하십시오. 배터리 지원 캐시가있는 RAID 컨트롤러가 최소한 하나 필요합니다.

작은 내구성 히트를 취할 수 있다면 innodb_flush_log_at_trx_commit을 0 또는 2로 설정하여 InnoDB를 사용할 수 있으며 (자세한 내용은 문서 참조) 성능을 향상시킬 수 있습니다.

구글과 다른 사람들의 동시성을 증가시킬 수있는 패치가 많이 있습니다. 패치 없이는 충분한 성능을 얻을 수 없다면 관심을 가질 수 있습니다.


질문과 대부분의 답변이 오래되었습니다 .

예, MyISAM이 InnoDB보다 빠르다는 것은 오래된 아내의 이야기입니다. 질문 날짜를 확인하십시오 : 2008; 이제 거의 10 년이 지났습니다. InnoDB는 그 이후로 상당한 성능 향상을 이루었습니다.

: 극적인 그래프의 MyISAM가 승리 한 경우를했다 COUNT(*) 없이WHERE 절. 하지만 그것이 정말로 당신이 시간을 보내는 일입니까?

당신이 실행하는 경우 동시성 테스트를, InnoDB는 매우 가능성이 승리한다 하더라도 대하여MEMORY .

벤치마킹하는 동안 쓰기를 수행하면 SELECTsMyISAM MEMORY이 테이블 수준 잠금으로 인해 손실 될 가능성이 높습니다.

실제로 Oracle은 InnoDB가 8.0에서 MyISAM을 제외하고 모두 제거했을 정도로 더 낫다고 확신합니다.

질문은 초기 5.1의 일에 작성되었습니다. 그 이후로 이러한 주요 버전은 "일반 공급"으로 표시되었습니다.

  • 2010 : 5.5 (12 월에 .8)
  • 2013 : 5.6 (2 월에 .10)
  • 2015 : 5.7 (10 월에 .9)
  • 2018 : 8.0 (4 월 .11)

결론 : MyISAM을 사용하지 마십시오.


유의하시기 바랍니다 내가 오라클에 해당하지만, MySQL을 위해 진실하지 않은 것을 말 그렇다면, MySQL은 내 작품은 전적으로 개인과 내 자신의 시간에하고있는 동안 내 정규 교육과 경험, 오라클 것을, 나는 사과드립니다. 두 시스템이 많이 공유하지만 관계 이론 / 대수는 동일하고 관계형 데이터베이스는 여전히 관계형 데이터베이스이지만 여전히 많은 차이가 있습니다 !!

저는 특히 InnoDB가 트랜잭션 기반이라는 점 (행 수준 잠금뿐만 아니라)을 좋아합니다. 즉, 웹 응용 프로그램의 한 "작업"에 대해 여러 번 업데이트 / 삽입 / 생성 / 변경 / 삭제 / 등을 수행 할 수 있습니다. 발생하는 문제 는 이러한 변경 / 작업 중 일부만 커밋되고 나머지는 커밋되지 않는 경우 대부분의 경우 (데이터베이스의 특정 디자인에 따라) 충돌하는 데이터 / 구조를 가진 데이터베이스로 끝납니다.

참고 : Oracle에서는 create / alter / drop 문을 "DDL"(데이터 정의) 문이라고하며 암시 적으로 커밋을 트리거합니다. "DML"(데이터 조작)이라고하는 삽입 / 업데이트 / 삭제 문은 자동으로 커밋 되지 않지만 DDL, 커밋 또는 종료 / 종료가 수행 될 때 (또는 세션을 "자동 커밋"으로 설정 한 경우에만) 클라이언트가 자동 커밋하는 경우). Oracle과 함께 작업 할 때이를 인식하는 것이 중요하지만 MySQL이 두 가지 유형의 문을 어떻게 처리하는지 잘 모르겠습니다. 이 때문에 MySQL에 관해서는 확실하지 않다는 점을 분명히하고 싶습니다. Oracle에서만 가능합니다.

트랜잭션 기반 엔진이 탁월한 경우의 예 :

나 또는 귀하가 무료 이벤트에 참석하기 위해 웹 페이지에 등록하고 있다고 가정 해 봅시다. 시스템의 주요 목적 중 하나는 좌석 제한이므로 최대 100 명까지만 등록 할 수 있습니다. 이벤트. 100 개의 가입에 도달하면 시스템은 적어도 다른 사람이 취소 할 때까지 추가 가입을 비활성화합니다.

이 경우 게스트 테이블 (이름, 전화, 이메일 등)과 등록한 게스트 수를 추적하는 두 번째 테이블이있을 수 있습니다. 따라서 하나의 "트랜잭션"에 대해 두 가지 작업이 있습니다. 이제 게스트 정보가 GUESTS 테이블에 추가 된 후 연결이 끊어 지거나 동일한 영향을 미치는 오류가 있다고 가정합니다. GUESTS 테이블이 업데이트 (삽입)되었지만 "사용 가능한 좌석"이 업데이트되기 전에 연결이 끊어졌습니다.

이제 게스트 테이블에 게스트가 추가되었지만 사용 가능한 좌석 수가 이제 올바르지 않습니다 (예 : 실제로 84 인 경우 값은 85 임).

물론 이를 처리하는 방법은 여러 가지가 있습니다. "게스트 테이블에서 행 수를 뺀 100"을 사용하여 사용 가능한 좌석을 추적하거나 정보가 일관 적인지 확인하는 코드 등 ...하지만 트랜잭션 기반 데이터베이스를 사용하는 경우 InnoDB와 같은 엔진, 모든 작업이 커밋되거나 아무것도 수행 되지 않습니다. 이것은 많은 경우에 도움이 될 수 있지만 내가 말했듯이 안전을위한 유일한 방법은 아닙니다. (하지만 좋은 방법은 프로그래머 / 스크립트 작성자가 아니라 데이터베이스에서 처리합니다).

이것이 전부 "트랜잭션 기반"이라는 것은 본질적으로이 맥락에서 내가 무언가를 놓치지 않는 한 전체 트랜잭션이 성공하거나 변경 되지 않은 것을 의미합니다. 부분적인 변경 만 수행하면 경미한 엉망이 될 수 있기 때문입니다. 데이터베이스를 손상시킬 수도 있습니다.

하지만 한 번 더 말하겠습니다. 그것이 엉망이되는 것을 피하는 유일한 방법은 아닙니다. 그러나 이것은 엔진 자체가 처리하는 방법 중 하나이므로 수동이 아닌 "트랜잭션 성공 여부, 그렇지 않은 경우 어떻게해야합니까 (예 : 재시도)"에 대해서만 걱정할 필요가있는 코드 / 스크립트로 남겨집니다. 데이터베이스 외부에서 "수동으로"확인하는 코드를 작성하고 이러한 이벤트에 대해 더 많은 작업을 수행합니다.

마지막으로 테이블 잠금과 행 잠금에 대한 참고 사항 :

면책 조항 : MySQL과 관련하여 다음과 같은 모든 내용이 틀렸을 수 있으며, 가상 / 예제 상황을 조사해야하지만 MySQL에서 손상을 일으킬 수 있는 것이 정확히 무엇인지 잘못되었을 수 있습니다 . 그러나 예제는 일반적인 프로그래밍에서 매우 현실적입니다. 비록 MySQL에 그러한 것들을 피하기위한 더 많은 메커니즘이 있더라도 ...

어쨌든 나는 한 번에 몇 개의 연결이 허용되는지 는 잠긴 테이블에서 작동 하지 않는다고 주장하는 사람들과 동의하는 데 상당히 확신 합니다. 사실 다중 연결 은 테이블 잠금의 전체 포인트입니다 !! 따라서 다른 프로세스 / 사용자 / 앱이 동시에 변경하여 데이터베이스를 손상시킬 수 없습니다.

같은 행에서 작업하는 두 개 이상의 연결이 어떻게 당신에게 정말 나쁜 하루를 만들까요 ?? 동일한 행에서 동일한 값을 업데이트하기를 원하거나 필요로하는 두 개의 프로세스가 있다고 가정합니다. 행이 버스 투어의 기록이고 두 프로세스 각각이 동시에 "riders"또는 "available_seats"를 업데이트하기를 원하기 때문이라고 가정합니다. 필드를 "현재 값에 1을 더한 값"으로

단계별로 가상으로이 작업을 수행해 보겠습니다.

  1. Process one은 현재 값을 읽습니다. 비어 있다고 가정 해 보겠습니다. 따라서 지금까지 '0'입니다.
  2. 프로세스 2는 현재 값도 읽습니다. 여전히 0입니다.
  3. 1 인 쓰기 (현재 + 1)를 처리합니다.
  4. 프로세스 2 2를 써야 하지만 프로세스 1이 새 값을 쓰기 전에 현재 값을 읽었 으므로 테이블에도 1을 씁니다.

확실하지 두 개의 연결이, 그렇게 첫 번째 쓰기 전에 모두 독서를 뒤섞다 수 있다고 ...하지만 그렇지 않다면, 난 여전히 문제를 볼 것입니다 :

  1. 프로세스 1은 현재 값인 0을 읽습니다.
  2. 하나의 쓰기 처리 (현재 + 1), 즉 1입니다.
  3. 프로세스 2는 현재 값을 읽습니다. 그러나 하나의 DID 쓰기 (업데이트)를 처리하는 동안 데이터를 커밋하지 않았으므로 동일한 프로세스 만 업데이트 된 새 값을 읽을 수 있고 다른 모든 프로세스는 커밋이있을 때까지 이전 값을 볼 수 있습니다.

또한 최소한 Oracle 데이터베이스에는 격리 수준이 있으므로 의역을하는 데 시간을 낭비하지 않을 것입니다. 여기에 그 주제에 대한 좋은 기사가 있으며, 각 격리 수준은 장단점을 가지고 있으며, 이는 트랜잭션 기반 엔진이 데이터베이스에서 얼마나 중요한지에 대해 설명합니다.

마지막으로, MyISAM 내에 외래 키 및 트랜잭션 기반 상호 작용 대신 다른 보호 장치가있을 수 있습니다. 하나는 전체 테이블이 잠겨있어 트랜잭션 / FK가 필요할 가능성이 적다는 사실이 있습니다 .

그리고 아쉽게도 이러한 동시성 문제를 알고 있다면 안전하지 않고 애플리케이션을 작성하고 이러한 오류가 발생하지 않도록 시스템을 설정할 수 있습니다 (데이터베이스 자체가 아니라 코드가 책임집니다). 그러나 제 생각에는 가능한 한 많은 보호 장치를 사용하고 방어 적으로 프로그래밍하며 사람의 실수는 완전히 피할 수 없다는 것을 항상 인식하는 것이 가장 좋습니다. 그것은 모든 사람에게 발생하며, 자신이 면역이된다고 말하는 사람은 거짓말을하거나 "Hello World"애플리케이션 / 스크립트를 작성하는 것 이상을하지 않았을 것입니다. ;-)

나는 그 중 일부가 누군가에게 도움이되기를 바랍니다. 그리고 더 나아가서, 나는 단지 지금 내가 가정의 범인이 아니고 실수하는 인간이 아니기를 바랍니다 !! 그럴 경우 미안하지만, 예를 생각하고 위험을 조사하는 등의 좋은 예는이 특정 맥락에서 잠재력이 없더라도 좋습니다.

저를 수정하고,이 "답변"을 편집하고, 투표를 거부하십시오. 내 잘못된 가정을 다른 사람으로 수정하기보다는 개선하려고 노력하십시오. ;-)

이것이 저의 첫 번째 답변이므로 모든 면책 조항 등으로 인해 길이를 용서해주십시오. 절대 확실하지 않을 때 오만하게 들리고 싶지 않습니다!


나는 이것이 차이점을 설명하고 다른 하나를 사용해야 할 때에 대한 훌륭한 기사라고 생각합니다 : http://tag1consulting.com/MySQL_Engines_MyISAM_vs_InnoDB


또한 MySQL 자체에 대한 몇 가지 드롭 인 교체를 확인하십시오.

MariaDB

http://mariadb.org/

MariaDB는 MySQL을위한 드롭 인 교체 기능을 제공하는 데이터베이스 서버입니다. MariaDB는 MySQL의 원본 작성자 중 일부가 무료 및 오픈 소스 소프트웨어 개발자로 구성된 광범위한 커뮤니티의 도움을 받아 구축되었습니다. MySQL의 핵심 기능 외에도 MariaDB는 대체 스토리지 엔진, 서버 최적화 및 패치를 비롯한 다양한 기능 향상을 제공합니다.

Percona 서버

https://launchpad.net/percona-server

향상된 성능, 향상된 진단 및 추가 된 기능으로 MySQL을위한 향상된 드롭 인 대체품입니다.


내 경험상 MyISAM은 DELETE, UPDATE, 많은 단일 INSERT, 트랜잭션 및 전체 텍스트 인덱싱을 수행하지 않는 한 더 나은 선택이었습니다. BTW, CHECK TABLE은 끔찍합니다. 행 수 측면에서 테이블이 오래됨에 따라 언제 끝날지 알 수 없습니다.


Myisam이 잠금 경합을 가지고 있음에도 불구하고 그것이 사용하는 빠른 잠금 획득 체계로 인해 대부분의 시나리오에서 InnoDb보다 여전히 빠르다는 것을 알아 냈습니다. 나는 Innodb를 여러 번 시도했으며 항상 한 가지 이유로 MyIsam으로 돌아갑니다. 또한 InnoDB는 엄청난 쓰기로드에서 CPU를 매우 많이 사용할 수 있습니다.


모든 응용 프로그램에는 데이터베이스 사용에 대한 자체 성능 프로필이 있으며 시간이 지남에 따라 변경 될 가능성이 있습니다.

할 수있는 가장 좋은 방법은 옵션을 테스트하는 것입니다. MyISAM과 InnoDB 사이를 전환하는 것은 간단하므로 테스트 데이터를로드하고 사이트에 대해 jmeter를 실행하고 어떤 일이 발생하는지 확인하십시오.


MyISAM 및 InnoDB 테이블에 임의의 데이터 삽입을 시도했습니다. 그 결과는 매우 충격적이었습니다. MyISAM은 InnoDB보다 단 1 만 개의 행을 삽입하는 데 몇 초가 더 적게 필요했습니다!


myisam은 해당 유형의 워크로드 (높은 동시성 쓰기)에 대한 NOGO입니다. innodb에 대한 경험이 많지 않습니다 (3 번 테스트하고 각 경우에 성능이 좋지 않다는 것을 발견했지만 마지막 테스트 이후 오랜 시간이 걸렸습니다). mysql을 실행하도록 강요하지 않고 동시 쓰기를 훨씬 더 잘 처리하므로 postgres를 시도해보십시오.


요컨대, InnoDB는 많은 INSERT 및 UPDATE 명령을 처리 할 수있는 신뢰할 수있는 데이터베이스를 필요로하는 작업에 적합합니다.

MyISAM은 테이블 잠금에 대한 단점을 고려할 때 쓰기 (INSERT 및 UPDATES)보다 많은 읽기 (SELECT) 명령을 사용하는 데이터베이스가 필요한 경우 유용합니다.

체크 아웃 할 수 있습니다.
InnoDB의
장단점 MyISAM의 장단점


나는 이것이 인기가 없을 것이라는 것을 알고 있지만 여기에 간다.

myISAM은 트랜잭션 및 참조 무결성과 같은 데이터베이스 필수 사항에 대한 지원이 부족하여 종종 결함이 있거나 버그가있는 응용 프로그램을 초래합니다. DB 엔진에서 지원하지 않는 경우 적절한 데이터베이스 설계 기본 사항을 배울 수 없습니다.

데이터베이스 세계에서 참조 무결성이나 트랜잭션을 사용하지 않는 것은 소프트웨어 세계에서 객체 지향 프로그래밍을 사용하지 않는 것과 같습니다.

InnoDB가 지금 존재합니다. 대신 사용하세요! myISAM이 모든 레거시 시스템의 기본값이었던 원래 엔진 임에도 불구하고 MySQL 개발자조차도이를 최신 버전의 기본 엔진으로 변경하는 데 동의했습니다.

읽거나 쓰는지 또는 어떤 성능 고려 사항이 있는지 여부는 중요하지 않습니다. myISAM을 사용하면 방금 만난 다음과 같은 다양한 문제가 발생할 수 있습니다. 데이터베이스 동기화를 수행하고 동시에 다른 사람 myISAM으로 설정된 테이블에 액세스 한 애플리케이션에 액세스했습니다. 트랜잭션 지원이 부족하고이 엔진의 일반적으로 낮은 안정성으로 인해 전체 데이터베이스가 충돌하고 수동으로 mysql을 다시 시작해야했습니다!

지난 15 년의 개발 기간 동안 저는 많은 데이터베이스와 엔진을 사용해 왔습니다. myISAM은이 기간 동안 다른 데이터베이스에서 한 번만 나에게 충돌했습니다! 그리고 그것은 일부 개발자가 결함이있는 CLR 코드 (공용 언어 런타임-기본적으로 데이터베이스 내부에서 실행되는 C # 코드)를 작성한 Microsoft SQL 데이터베이스 였지만 정확히 데이터베이스 엔진의 결함이 아닙니다.

나는 고품질의 고 가용성, 고성능 응용 프로그램이 myISAM이 작동하지 않을 것이기 때문에 사용해서는 안된다는 다른 답변에 동의합니다 . 만족스럽지 않은 경험을 제공 할만큼 견고하거나 안정적이지 않습니다. 자세한 내용은 Bill Karwin의 답변을 참조하십시오.

PS Gotta는 myISAM 팬보이가 반대 투표를 할 때 그것을 좋아하지만이 답변의 어느 부분이 잘못된 것인지 말할 수 없습니다.


읽기 / 쓰기 비율에 대해 InnoDB가 더 잘 수행 될 것이라고 생각합니다. 더티 읽기에 문제가 없으므로 슬레이브로 복제하고 모든 읽기를 슬레이브로 보낼 수 있습니다. 또한 한 번에 하나의 레코드가 아닌 대량으로 삽입하는 것을 고려하십시오.


새 프로젝트를 시작할 때마다이 질문을 Google에서 검색하여 새로운 답변이 있는지 확인합니다.

결국 결론은 다음과 같습니다. 최신 버전의 MySQL을 사용하고 테스트를 실행합니다.

키 / 값 조회를 원하는 테이블이 있습니다. 그게 전부입니다. 해시 키의 값 (0-512 바이트)을 가져와야합니다. 이 DB에는 트랜잭션이 많지 않습니다. 테이블은 가끔 (전체적으로) 업데이트되지만 트랜잭션은 0입니다.

그래서 우리는 여기서 복잡한 시스템에 대해 이야기하는 것이 아니라 간단한 조회에 대해 이야기하고 있습니다. 그리고 (테이블 RAM을 상주시키는 것 외에) 성능을 최적화 할 수있는 방법입니다.

또한 다른 데이터베이스 (예 : NoSQL)에 대한 테스트를 수행하여 이점을 얻을 수있는 곳이 있는지 확인합니다. 내가 찾은 가장 큰 장점은 키 매핑에 있지만 조회가 진행되는 한 MyISAM은 현재 모두를 차지하고 있습니다.

비록 나는 MyISAM 테이블로 금융 거래를 수행하지 않을 것이지만, 간단한 조회를 위해서는 그것을 테스트해야합니다. 일반적으로 초당 2 배에서 5 배의 질의.

테스트 해보세요. 토론을 환영합니다.


70 % 삽입과 30 % 읽기라면 InnoDB 측과 더 비슷합니다.


결론 : 많은 양의 데이터를 선택하여 오프라인으로 작업하는 경우 MyISAM은 아마도 더 나은 (훨씬 더 나은) 속도를 제공 할 것입니다.

MyISAM이 InnoDB보다 훨씬 더 효율적인 경우가 있습니다. 오프라인으로 대용량 데이터 덤프를 조작 할 때 (테이블 잠금으로 인해).

예 : VARCHAR 필드를 키로 사용하는 NOAA에서 csv 파일 (15M 레코드)을 변환했습니다. InnoDB는 많은 양의 메모리를 사용할 수 있어도 영원히 걸렸습니다.

이것은 csv의 예입니다 (첫 번째 및 세 번째 필드는 키임).

USC00178998,20130101,TMAX,-22,,,7,0700
USC00178998,20130101,TMIN,-117,,,7,0700
USC00178998,20130101,TOBS,-28,,,7,0700
USC00178998,20130101,PRCP,0,T,,7,0700
USC00178998,20130101,SNOW,0,T,,7,

내가해야 할 일은 관측 된 기상 현상의 일괄 오프라인 업데이트를 실행하는 것이므로 데이터를 수신하기 위해 MyISAM 테이블을 사용하고 키에서 JOINS를 실행하여 들어오는 파일을 정리하고 VARCHAR 필드를 INT 키로 바꿀 수 있습니다 (관련된 원래 VARCHAR 값이 저장된 외부 테이블).

참고 URL : https://stackoverflow.com/questions/20148/myisam-versus-innodb

반응형