2012-02-27 38 views
14

tình hình của tôi:Làm thế nào để tối ưu hóa truy vấn chậm với nhiều tham gia

  • truy vấn tìm kiếm khoảng 90.000 xe
  • truy vấn mất lâu mỗi lần
  • Tôi đã có chỉ số trên tất cả các lĩnh vực được gia nhập.

Làm cách nào để tối ưu hóa?

Đây là truy vấn:

SELECT vehicles.make_id, 
     vehicles.fuel_id, 
     vehicles.body_id, 
     vehicles.transmission_id, 
     vehicles.colour_id, 
     vehicles.mileage, 
     vehicles.vehicle_year, 
     vehicles.engine_size, 
     vehicles.trade_or_private, 
     vehicles.doors, 
     vehicles.model_id, 
     Round(3959 * Acos(Cos(Radians(51.465436)) * 
         Cos(Radians(vehicles.gps_lat)) * 
              Cos(
              Radians(vehicles.gps_lon) - Radians(
              -0.296482)) + 
           Sin(
             Radians(51.465436)) * Sin(
           Radians(vehicles.gps_lat)))) AS distance 
FROM vehicles 
     INNER JOIN vehicles_makes 
     ON vehicles.make_id = vehicles_makes.id 
     LEFT JOIN vehicles_models 
     ON vehicles.model_id = vehicles_models.id 
     LEFT JOIN vehicles_fuel 
     ON vehicles.fuel_id = vehicles_fuel.id 
     LEFT JOIN vehicles_transmissions 
     ON vehicles.transmission_id = vehicles_transmissions.id 
     LEFT JOIN vehicles_axles 
     ON vehicles.axle_id = vehicles_axles.id 
     LEFT JOIN vehicles_sub_years 
     ON vehicles.sub_year_id = vehicles_sub_years.id 
     INNER JOIN members 
     ON vehicles.member_id = members.id 
     LEFT JOIN vehicles_categories 
     ON vehicles.category_id = vehicles_categories.id 
WHERE vehicles.status = 1 
     AND vehicles.date_from < 1330349235 
     AND vehicles.date_to > 1330349235 
     AND vehicles.type_id = 1 
     AND (vehicles.price >= 0 
      AND vehicles.price <= 1000000) 

Dưới đây là lược đồ bảng xe:

CREATE TABLE IF NOT EXISTS `vehicles` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `number_plate` varchar(100) NOT NULL, 
    `type_id` int(11) NOT NULL, 
    `make_id` int(11) NOT NULL, 
    `model_id` int(11) NOT NULL, 
    `model_sub_type` varchar(250) NOT NULL, 
    `engine_size` decimal(12,1) NOT NULL, 
    `vehicle_year` int(11) NOT NULL, 
    `sub_year_id` int(11) NOT NULL, 
    `mileage` int(11) NOT NULL, 
    `fuel_id` int(11) NOT NULL, 
    `transmission_id` int(11) NOT NULL, 
    `price` decimal(12,2) NOT NULL, 
    `trade_or_private` tinyint(4) NOT NULL, 
    `postcode` varchar(25) NOT NULL, 
    `gps_lat` varchar(50) NOT NULL, 
    `gps_lon` varchar(50) NOT NULL, 
    `img1` varchar(100) NOT NULL, 
    `img2` varchar(100) NOT NULL, 
    `img3` varchar(100) NOT NULL, 
    `img4` varchar(100) NOT NULL, 
    `img5` varchar(100) NOT NULL, 
    `img6` varchar(100) NOT NULL, 
    `img7` varchar(100) NOT NULL, 
    `img8` varchar(100) NOT NULL, 
    `img9` varchar(100) NOT NULL, 
    `img10` varchar(100) NOT NULL, 
    `is_featured` tinyint(4) NOT NULL, 
    `body_id` int(11) NOT NULL, 
    `colour_id` int(11) NOT NULL, 
    `doors` tinyint(4) NOT NULL, 
    `axle_id` int(11) NOT NULL, 
    `category_id` int(11) NOT NULL, 
    `contents` text NOT NULL, 
    `date_created` int(11) NOT NULL, 
    `date_edited` int(11) NOT NULL, 
    `date_from` int(11) NOT NULL, 
    `date_to` int(11) NOT NULL, 
    `member_id` int(11) NOT NULL, 
    `inactive_id` int(11) NOT NULL, 
    `status` tinyint(4) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `type_id` (`type_id`), 
    KEY `make_id` (`make_id`), 
    KEY `model_id` (`model_id`), 
    KEY `fuel_id` (`fuel_id`), 
    KEY `transmission_id` (`transmission_id`), 
    KEY `body_id` (`body_id`), 
    KEY `colour_id` (`colour_id`), 
    KEY `axle_id` (`axle_id`), 
    KEY `category_id` (`category_id`), 
    KEY `vehicle_year` (`vehicle_year`), 
    KEY `mileage` (`mileage`), 
    KEY `status` (`status`), 
    KEY `date_from` (`date_from`), 
    KEY `date_to` (`date_to`), 
    KEY `trade_or_private` (`trade_or_private`), 
    KEY `doors` (`doors`), 
    KEY `price` (`price`), 
    KEY `engine_size` (`engine_size`), 
    KEY `sub_year_id` (`sub_year_id`), 
    KEY `member_id` (`member_id`), 
    KEY `date_created` (`date_created`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=136237 ; 

Các GIẢI THÍCH:

1 SIMPLE vehicles ref  type_id,make_id,status,date_from,date_to,price,mem... type_id  4 const 85695 Using where 
1 SIMPLE members  index PRIMARY  PRIMARY  4 NULL 3 Using where; Using index; Using join buffer 
1 SIMPLE vehicles_makes eq_ref PRIMARY  PRIMARY  4 tvs.vehicles.make_id 1 Using index 
1 SIMPLE vehicles_models  eq_ref PRIMARY  PRIMARY  4 tvs.vehicles.model_id 1 Using index 
1 SIMPLE vehicles_fuel eq_ref PRIMARY  PRIMARY  4 tvs.vehicles.fuel_id 1 Using index 
1 SIMPLE vehicles_transmissions eq_ref PRIMARY  PRIMARY  4 tvs.vehicles.transmission_id 1 Using index 
1 SIMPLE vehicles_axles eq_ref PRIMARY  PRIMARY  4 tvs.vehicles.axle_id 1 Using index 
1 SIMPLE vehicles_sub_years eq_ref PRIMARY  PRIMARY  4 tvs.vehicles.sub_year_id 1 Using index 
1 SIMPLE vehicles_categories  eq_ref PRIMARY  PRIMARY  4 tvs.vehicles.category_id 1 Using index 
+0

Bạn có thể cung cấp GIẢI THÍCH không? –

+0

Đã cập nhật bài đăng gốc. – ChimeraTheory

Trả lời

11

Cải thiện mệnh đề WHERE

của bạn GIẢI THÍCH cho thấy MySQL là chỉ sử dụng một chỉ mục (type_id) để lựa chọn các hàng phù hợp với quy định tại khoản WHERE, mặc dù bạn có nhiều tiêu chí trong mệnh đề.

Để có thể sử dụng chỉ mục cho tất cả các tiêu chí trong mệnh đề WHERE và để giảm kích thước của tập hợp kết quả càng nhanh càng tốt, hãy thêm chỉ mục nhiều cột vào các cột sau trên bảng phương tiện:

(status, date_from, date_to, type_id, price) 

Các cột phải theo thứ tự cardinality cao nhất ít nhất.

Ví dụ, vehicles.date_from có thể có giá trị khác biệt hơn status, vì vậy đặt cột date_from trước status, như thế này:

(date_from, date_to, price, type_id, status) 

này nên giảm các hàng trả lại trong phần đầu của việc thực hiện truy vấn và phải được chứng minh bằng số lượng hàng thấp hơn trên dòng đầu tiên của kết quả EXPLAIN.

Bạn cũng sẽ nhận thấy rằng MySQL sẽ sử dụng chỉ mục nhiều cột cho WHERE trong kết quả GIẢI THÍCH. Nếu, tình cờ, nó không, bạn nên gợi ý hoặc ép chỉ số đa cột.

Tháo không cần thiết JOIN

Nó không xuất hiện mà bạn đang sử dụng bất kỳ lĩnh vực trong bất kỳ các bảng tham gia, vì vậy loại bỏ các tham gia. Điều này sẽ xóa tất cả công việc bổ sung của truy vấn và đưa bạn xuống một, kế hoạch thực hiện đơn giản (một dòng trong kết quả GIẢI THÍCH).

Mỗi bảng Đã tham gia gây ra một tra cứu bổ sung cho mỗi hàng của tập hợp kết quả. Vì vậy, nếu mệnh đề WHERE chọn 5.000 hàng từ xe, vì bạn có 8 tham gia vào các phương tiện, bạn sẽ có 5.000 * 8 = 40.000 tra cứu. Đó là rất nhiều để hỏi từ máy chủ cơ sở dữ liệu của bạn.

+0

Nếu các trường chúng tôi so sánh đến từ các bảng được nối, việc lập chỉ mục có hữu ích không? –

1

làm bạn cũng có inde XES bằng các:

vehicles.status 
vehicles.date_from 
vehicles.date_to 
vehicles.type_id 
vehicles.price 
+0

Có, xem ở trên. – ChimeraTheory

1

Để cụ thể hơn một chút so với @Randy các chỉ số, tôi tin rằng ý định của mình là phải có một chỉ số COMPOUND để tận dụng những tiêu chí truy vấn của bạn ... Một chỉ số được xây dựng trên một TỐI THIỂU của ...

(status, type_id, date_from) 

nhưng có thể được mở rộng để bao gồm các date_to và giá cả quá, nhưng không biết bao nhiêu chỉ số tại rằng mức độ hạt thực sự có thể giúp

(status, type_id, date_from, date_to, price) 

CHỈNH SỬA cho mỗi Nhận xét

Bạn không cần tất cả các chỉ mục riêng lẻ đó ... Có, khóa chính của chính nó. Tuy nhiên, đối với những người khác, bạn nên có các chỉ mục phức hợp dựa trên những tiêu chí truy vấn phổ biến của bạn có thể là gì và loại bỏ các tiêu chí khác ... động cơ có thể bị lẫn lộn trên đó có thể phù hợp nhất với truy vấn. Nếu bạn biết bạn luôn tìm kiếm một trạng thái, loại và ngày cụ thể (giả sử tìm kiếm xe), hãy làm điều đó như một chỉ mục. Nếu truy vấn đang tìm kiếm thông tin đó, nhưng cũng có giá trong tiêu chí đó, nó sẽ rất gần với một vài bản ghi được lập chỉ mục đủ điều kiện và bay qua giá như chỉ là một tiêu chí bổ sung.

Nếu bạn cung cấp truy vấn như Chỉ Tự động so với hộp số tay bất kể năm/thực hiện, thì có, đó có thể là chỉ mục của riêng nó. Tuy nhiên, nếu bạn có thể LOẠI có một số tiêu chí "phổ biến" khác, thì đó là tiêu chí thứ cấp có thể được sử dụng trong truy vấn. Ví dụ: nếu bạn tìm kiếm Hộp số tay bằng 2 cửa và 4 cửa, hãy có chỉ mục của bạn trên (transmission_id, category_id).

Một lần nữa, bạn muốn mọi thứ sẽ giúp thu hẹp trường tiêu chí dựa trên một số điều kiện "tối thiểu". Nếu bạn tack vào một cột thêm vào chỉ mục có thể "thường" được áp dụng, điều đó sẽ chỉ giúp hiệu suất.

+0

Tôi không quen với các chỉ mục phức hợp - vui lòng xem bài đăng cập nhật của tôi. Việc lập chỉ mục hiện tại của tôi có hiệu quả không? – ChimeraTheory

+0

Chỉ cần thêm một chỉ mục khác, nhưng thay vì cột SINGLE, chỉ cần làm như trên, nhiều cột được phân tách bằng các cột ... Bằng cách này, một chỉ mục có thể có nhiều thành phần để khớp chặt chẽ hơn với tiêu chí truy vấn. – DRapp

+0

Tôi có 21 chỉ mục, tôi cần nhóm nào và sau đó có cần xóa chúng trước không? – ChimeraTheory

4

Thay vì tính toán tốn kém khoảng cách chính xác cho tất cả của các hàng sử dụng hộp giới hạn và chỉ tính khoảng cách chính xác cho các hàng bên trong hộp.

Ví dụ đơn giản nhất có thể là tính toán kinh độ và vĩ độ tối thiểu/phút mà bạn quan tâm và thêm nó vào mệnh đề WHERE. Bằng cách này, khoảng cách sẽ chỉ được tính cho một tập con của các hàng.

WHERE 
    vehicles.gps_lat > min_lat ANDd vehicles.gps_lat < max_lat AND 
    vehicles.gps_lon > min_lon AND vehicles.gps_lon < max_lon 

Đối với các giải pháp phức tạp hơn xem:

3

là bạn SQL nhanh hơn mà không cần điều này?

Round(3959 * Acos(Cos(Radians(51.465436)) * 
    Cos(Radians(vehicles.gps_lat)) * 
    Cos(Radians(vehicles.gps_lon) - 
    Radians(-0.296482)) + 
    Sin(Radians(51.465436)) * 
    Sin(Radians(vehicles.gps_lat)))) AS distance 

biểu diễn phương trình toán học rất đắt

Có lẽ bạn nên xem xét một cái nhìn cụ thể hóa mà trước tính bạn khoảng cách, và bạn có thể chọn từ quan điểm đó. Tùy thuộc vào cách dữ liệu động của bạn, bạn có thể không phải làm mới dữ liệu của bạn quá thường xuyên.

+0

Hơi có nhưng tôi cần điều đó trong đó ... – ChimeraTheory

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