2012-03-30 49 views
8

Tôi có bảng mysql với hơn 30 triệu bản ghi ban đầu được lưu trữ với myisam. Dưới đây là một mô tả của bảng:Hiệu suất khác biệt giữa Innodb và Myisam trong Mysql

describe_table

tôi sẽ chạy các truy vấn sau đây với bảng này mà thường sẽ mất khoảng 30 giây để hoàn thành. Tôi sẽ thay đổi @eid mỗi lần để tránh cơ sở dữ liệu hoặc đĩa đệm.

select count(fact_data.id) 
    from fact_data 
    where [email protected] 
     and fact_data.metric_id=1 

Sau đó, tôi chuyển đổi bảng này thành innoDB mà không thực hiện bất kỳ thay đổi nào khác và sau đó cùng một truy vấn trở lại dưới mỗi giây một lần tôi chạy truy vấn. Ngay cả khi tôi đặt ngẫu nhiên @eid để tránh lưu vào bộ nhớ cache, truy vấn sẽ trả về sau một giây.

Tôi đã nghiên cứu sự khác biệt giữa hai loại lưu trữ để cố gắng giải thích sự cải thiện đáng kể về hiệu suất nhưng không thể tìm ra bất kỳ thứ gì. Trong thực tế, phần lớn những gì tôi đọc chỉ ra rằng Myisam nên nhanh hơn.

Các truy vấn tôi đang chạy là chống lại cơ sở dữ liệu cục bộ mà không có quy trình nào khác nhấn vào cơ sở dữ liệu tại thời điểm thử nghiệm.

Trả lời

15

Đó là sự khác biệt đáng kể về hiệu suất lớn, nhưng tôi có thể nghĩ ra một vài điều có thể đóng góp.

MyISAM trong lịch sử được xem nhanh hơn InnoDB, nhưng đối với các phiên bản gần đây của InnoDB, điều đó đúng với một nhóm nhỏ hơn nhiều, rất nhiều trường hợp sử dụng. MyISAM thường nhanh hơn cho việc quét bảng của các bảng chỉ đọc. Trong hầu hết các trường hợp sử dụng khác, tôi thường thấy InnoDB nhanh hơn. Thường nhanh gấp nhiều lần. Bảng khóa là một Knell chết cho MyISAM trong hầu hết việc sử dụng MySQL của tôi.

Bộ nhớ cache MyISAM lập chỉ mục trong bộ đệm khóa của nó. Có lẽ bạn đã thiết lập bộ đệm khóa quá nhỏ để nó có hiệu quả lưu trữ chỉ mục cho bảng hơi lớn của bạn.

MyISAM phụ thuộc vào hệ điều hành để lưu trữ dữ liệu bảng từ tệp .MYD trong bộ đệm đĩa của hệ điều hành. Nếu hệ điều hành đang chạy thấp trên bộ nhớ, nó sẽ bắt đầu đổ bộ nhớ đệm đĩa của nó. Điều đó có thể buộc nó phải đọc từ đĩa.

InnoDB lưu trữ cả hai chỉ mục và dữ liệu trong bộ đệm bộ nhớ riêng của nó. Bạn có thể yêu cầu hệ điều hành không sử dụng bộ đệm đĩa nếu bạn đặt innodb_flush_method thành O_DIRECT, mặc dù điều này không được hỗ trợ trên OS X.

InnoDB thường đệm dữ liệu và chỉ mục trong trang 16kb. Tùy thuộc vào cách bạn thay đổi giá trị của @eid giữa các truy vấn, nó có thể đã lưu trữ dữ liệu cho một truy vấn do đĩa đọc từ truy vấn trước đó.

Đảm bảo bạn đã tạo các chỉ mục giống hệt nhau. Sử dụng giải thích để kiểm tra xem MySQL có đang sử dụng chỉ mục hay không. Vì bạn bao gồm đầu ra của mô tả thay vì hiển thị tạo bảng hoặc chỉ mục hiển thị từ, tôi không thể biết thực thể_id có phải là một phần của chỉ mục tổng hợp hay không. Nếu nó không phải là phần đầu tiên của một chỉ số tổng hợp, nó sẽ không được sử dụng.

Nếu bạn đang sử dụng một phiên bản tương đối hiện đại của MySQL, hãy chạy lệnh sau đây trước khi chạy truy vấn:

bộ hồ sơ = 1;

Điều đó sẽ bật hồ sơ truy vấn cho phiên của bạn. Sau khi chạy truy vấn, hãy chạy

hiển thị tiểu sử;

Điều đó sẽ hiển thị cho bạn danh sách các truy vấn mà tiểu sử có sẵn. Tôi nghĩ rằng nó giữ 20 cuối cùng theo mặc định. Giả sử truy vấn của bạn là truy vấn đầu tiên, hãy chạy:

hiển thị tiểu sử cho truy vấn 1;

Sau đó, bạn sẽ thấy thời lượng của mỗi giai đoạn trong khi chạy truy vấn của mình. Điều này cực kỳ hữu ích để xác định điều gì (ví dụ: khóa bảng, sắp xếp, tạo bảng tạm thời, v.v.) đang khiến truy vấn bị chậm.

6

Nghi ngờ đầu tiên của tôi là bảng và/hoặc chỉ mục MyISAM ban đầu đã bị phân mảnh theo thời gian dẫn đến hiệu suất giảm dần. Bảng InnoDB sẽ không có cùng một vấn đề kể từ khi bạn tạo ra nó với tất cả các dữ liệu đã có trong nó (vì vậy nó sẽ được lưu trữ tuần tự trên đĩa).

Bạn có thể kiểm tra lý thuyết này bằng cách xây dựng lại bảng MyISAM. Cách dễ nhất để thực hiện việc này là sử dụng câu lệnh ALTER TABLE "null":

ALTER TABLE mytable ENGINE = MyISAM; 

Sau đó kiểm tra hiệu suất để xem nó có tốt hơn không.

Một khả năng khác là nếu cơ sở dữ liệu được điều chỉnh đơn giản cho hiệu suất InnoDB thay vì MyISAM. Ví dụ, InnoDB sử dụng innodb_buffer_pool_size parameter để biết có bao nhiêu bộ nhớ nên được cấp phát để lưu trữ dữ liệu được lưu trong bộ nhớ cache và các chỉ mục trong bộ nhớ. Nhưng MyISAM sử dụng tham số key_buffer. Nếu cơ sở dữ liệu của bạn có một vùng đệm lớn và một bộ đệm khóa nhỏ, thì hiệu suất của InnoDB sẽ tốt hơn hiệu suất MyISAM, đặc biệt là cho các bảng lớn.

+0

Một thử nghiệm hợp lý đơn giản về việc tạo bảng MyISAM mới và thời gian truy vấn đối với bảng đó có thể xác nhận dự đoán này. –

1

Định nghĩa chỉ mục của bạn là gì, có nhiều cách để bạn có thể tạo chỉ mục cho MyISAM trong đó các trường chỉ mục của bạn sẽ không được sử dụng khi bạn nghĩ.

Các vấn đề liên quan