2011-01-04 41 views
6

Tôi có một bảng lớn mà từ đó tôi phải chọn một lượng lớn hàng.Chỉ số hợp chất MySQL không được sử dụng

Bảng lưu trữ các bản ghi chi tiết cuộc gọi (CDR). Ví dụ:

+-------------+--------------+------+-----+---------------------+----------------+ 
| Field  | Type   | Null | Key | Default    | Extra   | 
+-------------+--------------+------+-----+---------------------+----------------+ 
| id   | int(45)  | NO | PRI | NULL    | auto_increment | 
| calldate | datetime  | NO | MUL | 0000-00-00 00:00:00 |    | 
| accountcode | varchar(100) | NO |  |      |    | 
| other... | varchar(45) | NO |  |      |    | 

Kể từ khi truy vấn của tôi tìm kiếm một khách hàng các cuộc gọi trong ngày nào đó, tôi lập chỉ mục calldate và accountcode với nhau trong một nhóm chỉ số như sau:

CREATE TABLE `cdr` (
    `id` int(45) NOT NULL AUTO_INCREMENT, 
    `calldate` datetime NOT NULL DEFAULT '0000-00-00 00:00:00', 
    `accountcode` varchar(100) NOT NULL DEFAULT '', 
    other fields... 
PRIMARY KEY (`id`), 
KEY `date_acc` (`calldate`,`accountcode`) USING BTREE 
) ENGINE=MyISAM DEFAULT CHARSET=latin1 

Tuy nhiên, khi thực hiện các truy vấn sau, GIẢI THÍCH kết quả cho thấy chỉ có phần datetime của khóa đang được sử dụng:

Query:

SELECT * 
FROM cdr 
WHERE calldate > '2010-12-01' 
    AND accountcode = 'xxxxxx'; 

GIẢI THÍCH kết quả:

+----+-------------+-------+-------+---------------+----------+---------+------+---------+----------+-------------+ 
| id | select_type | table | type | possible_keys | key  | key_len | ref | rows | filtered | Extra  | 
+----+-------------+-------+-------+---------------+----------+---------+------+---------+----------+-------------+ 
| 1 | SIMPLE  | cdr | range | date_acc  | date_acc | 8  | NULL | 3312740 | 100.00 | Using where | 
+----+-------------+-------+-------+---------------+----------+---------+------+---------+----------+-------------+ 

Nó dường như chỉ 8 byte đầu tiên (phần ngày của khóa) đang được sử dụng. Tuy nhiên mệnh đề WHERE tham chiếu rõ ràng cả hai phần của khóa bằng AND, do đó, trong lý thuyết, toàn bộ khóa cần được sử dụng.

Tôi có nên tạo các chỉ mục riêng cho mã gọi và mã tài khoản và để trình tối ưu hóa truy vấn hợp nhất chúng không? Tại sao chỉ mục đầy đủ không được sử dụng?

Cảm ơn sự giúp đỡ!

+0

Dường như nó đã lọc 100% tất cả các hàng có truy vấn đó. Đó không phải là giá trị của cột được lọc là gì? Bạn có thể cung cấp một ví dụ không có bộ lọc đó không? Tôi đồng ý với một trong những câu trả lời dưới đây, bạn nên có bộ lọc đầu tiên, sau đó sắp xếp. chỉ mục tài khoản, calldate. Bạn sẽ nhận được kết quả tốt hơn nhiều. – TheJacobTaylor

Trả lời

6

Câu trả lời ngắn: Bạn có thể sử dụng chỉ mục hiệu quả hơn tại đây nếu khóa của bạn là (mã tài khoản, số gọi) thay vì (mã gọi, mã tài khoản).

Cách tốt nhất để hiểu vấn đề là bằng cách suy nghĩ về các phím đa cột như là một nối của các cột khác nhau. Ví dụ: nếu cột 1 có giá trị 'A, B, C, D' và cột 2 'W, X, Y, Z', bạn sẽ tạo chỉ mục trên 'AW, BX, CY, DZ', v.v ... và đặt tất cả của những người vào một cây B.

Để thực hiện một truy vấn phạm vi, bạn sẽ tìm thấy người kế thừa đầu tiên thấp của dải ô và lặp lại cho đến khi bạn vượt quá phạm vi trên. Điều này có nghĩa là bạn chỉ có thể sử dụng chỉ mục một cách hiệu quả để thực hiện truy vấn phạm vi trên hậu tố của khóa.

+0

Cảm ơn thông tin chi tiết về cách các truy vấn phạm vi hoạt động trên các khóa đa cột, giải thích rất có giá trị! Thật vậy, chỉ mục đầy đủ được sử dụng nếu các phím được sắp xếp theo cách khác. –

+0

@Vinay, Được cung cấp ** if ** 'accountcode' có số lượng thẻ lớn hơn' calldate'. – Pacerier

1

Vì bạn đang tìm kiếm một phạm vi ngày (> '2010-12-01'), tôi không thấy cách trình tối ưu hóa có thể sử dụng chỉ mục đầy đủ. Điều tốt nhất bạn có thể làm là quét phạm vi ngày tìm kiếm mã tài khoản phù hợp. Bây giờ, nếu bạn đang tìm kiếm chính xác một ngày và chính xác một mã tài khoản, thì tôi mong đợi chỉ mục đầy đủ sẽ được sử dụng.

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