2011-02-04 32 views
7

Tôi có một bảng MyISAM lớn. Nó đang tiếp cận 1 triệu hàng. Về cơ bản nó là một danh sách các mục và một số thông tin về chúng.Tại sao lớn hơn so với bằng tạo nên sự khác biệt trong MySQL SELECT?

Có hai chỉ số:

  • chính: ID mục
  • ngày (ngày) và col (int).

tôi chạy hai truy vấn:

SELECT * FROM table WHERE date = '2011-02-01' AND col < 5 LIMIT 10 

SELECT * FROM table WHERE date < '2011-02-01' AND col < 5 LIMIT 10 

Người đầu tiên kết thúc trong ~ 0,0005 giây và lần thứ hai trong ~ 0,05 giây. Đó là sự khác biệt 100X. Có sai lầm khi tôi mong đợi cả hai điều này chạy với tốc độ gần như giống nhau? Tôi không được hiểu rõ các chỉ số. Làm cách nào để tăng tốc truy vấn thứ hai?

+0

Đối với cả hai truy vấn, bao nhiêu hồ sơ phù hợp với vị đầu tiên? –

+0

40.000 cho bằng, 55.000 cho số ít hơn, do đó, nó không phải là một sự khác biệt lớn – burger

+0

@bigmac thử thay đổi định dạng chỉ mục và xem điều gì xảy ra. –

Trả lời

2

Bất kể Mysql nào, nó tóm tắt theo lý thuyết thuật toán cơ bản.

Lớn hơn và Ít hơn các thao tác trên một tập hợp lớn chậm hơn hoạt động Nhận dạng. Với một bộ dữ liệu lớn, cấu trúc dữ liệu lý tưởng để xác định ít hơn hoặc lớn hơn là một cây tự cân bằng (nhị phân hoặc n-tree). Trên cây tự cân bằng, kịch bản trường hợp xấu nhất để tìm tất cả ít hơn/lớn hơn là nhật ký n.

Cấu trúc dữ liệu lý tưởng để tra cứu danh tính là một hashtable. Hiệu suất của hashtables thường là O (1) hay còn gọi là thời gian cố định. Tuy nhiên, một hashtable là không tốt cho lớn/ít hơn.

Nói chung một cây cân bằng tốt chỉ hoạt động hơi kém hơn so với một hashtable (đó là cách Haskell lấy đi bằng cách sử dụng một cây cho hashtables).

Do đó bất kể những gì Mysql làm nó không ngạc nhiên rằng <,> là chậm hơn so với =

Old trả lời dưới đây:

Bởi vì thứ nhất là như tra cứu Hashtable từ trước đến nay '=' (đặc biệt nếu chỉ mục của bạn là một hashtable) nó sẽ nhanh hơn so với thứ hai có thể làm việc tốt hơn với một cây như chỉ mục.

Vì MySql cho phép định cấu hình định dạng chỉ mục mà bạn có thể thử thay đổi nhưng tôi chắc chắn lần đầu tiên sẽ luôn chạy nhanh hơn lần thứ hai.

+0

Liên kết tới tài liệu trên CREATE INDEX: http://dev.mysql.com/doc/refman/5.0/en/create-index.html –

+0

Vì bảng của tôi là MyISAM, tôi chỉ có thể có chỉ số BTREE. InnoDB cũng chỉ là BTREE. Tôi lo lắng về việc chuyển sang một công cụ lưu trữ ít chủ đạo hơn vì nó có thể liên quan đến các cảnh báo khác mà tôi có thể chưa biết. – burger

+0

Điều này cũng có thể giúp http://dev.mysql.com/doc/refman/5.5/en/index-btree-hash.html –

1

Dữ liệu đầu tiên thực hiện tìm kiếm dữ liệu ở vị trí thứ hai để quét. Quét luôn đắt hơn so với tìm kiếm do đó sự khác biệt thời gian.

Giống như vậy, quá trình quét có nghĩa là chạy qua tất cả các trang của cuốn sách khi tìm kiếm trực tiếp nhảy đến số trang.

Hy vọng điều này có thể hữu ích.

2

Tôi giả sử bạn có chỉ mục trên cột ngày. Truy vấn đầu tiên sử dụng chỉ mục, truy vấn thứ hai có thể thực hiện quét tuyến tính (ít nhất là trên một phần dữ liệu). Tìm nạp trực tiếp luôn nhanh hơn quét tuyến tính.

2

MySQL lưu trữ các chỉ mục của nó theo mặc định trong BTREE. Không băm nói chung.

Câu trả lời ngắn cho sự khác biệt hiệu suất là biểu mẫu < đánh giá nhiều nút hơn, sau đó là biểu mẫu =.

Chỉ số mà bạn đã có trên đó (ngày, col) lưu trữ các giá trị xấp xỉ như một danh bạ điện thoại:

2011-01-01, col=1, row_ptr 
2011-01-01, col=2, row_ptr 
2011-01-01, col=3, row_ptr 
etc... 
2011-02-01, col=1, row_ptr 
2011-02-01, col=2, row_ptr 
2011-02-01, col=3, row_ptr 
etc... 
2011-02-02, col=1, row_ptr 
2011-02-02, col=2, row_ptr 
etc... 

... tăng dần sắp xếp các nút cây kích thước B (2011-01- 01, col = 1) < (2011-01-01, col = 2) < (2011-01-02, col = 1).

Câu hỏi của bạn là về cơ bản hỏi sự khác nhau giữa:

  1. Tìm tất cả các số điện thoại với tên cuối cùng 'Smith' và tên đầu tiên bắt đầu bằng 'A'
  2. Tìm tất cả các số điện thoại mà đến trước 'Smith' và có tên bắt đầu bằng 'A'.

Rõ ràng lý do tại sao # 1 nhanh hơn rất nhiều rồi # 2.

Ngoài ra còn có những cân nhắc về hiệu suất bộ nhớ/đĩa và phân bổ đống (= WAY ít chuyển hơn <) chiếm số lượng không đáng kể nhưng phụ thuộc phần lớn vào phân phối dữ liệu và vị trí cụ thể của 2011-02-01, bản ghi chính col = min (col).

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