2015-05-12 14 views
5

Chúng tôi có một bảng với khoảng 25.000.000 hàng gọi là 'sự kiện' có giản đồ sau:truy vấn SQL: Tăng tốc cho các bảng lớn

TABLE events 
- campaign_id : int(10) 
- city  : varchar(60) 
- country_code : varchar(2) 

Các truy vấn sau đây có RẤT dài (> 2000 giây):

SELECT COUNT(*) AS counted_events, country_code 
FROM events 
WHERE campaign_id` in (597) 
GROUPY BY city, country_code 
ORDER BY counted_events 

Chúng tôi phát hiện ra rằng đó là vì phần GROUP BY.

Đã có chỉ mục idx_campaign_id_city_country_code trên (campaign_id, city, country_code) được sử dụng.

Có thể ai đó có thể đề xuất giải pháp tốt để tăng tốc độ?

Cập nhật:

'Giải thích' cho thấy rằng trong số nhiều chỉ số có thể MySql sử dụng này: 'idx_campaign_id_city_country_code', cho các hàng nó cho thấy: '471.304' và 'Extra' nó cho thấy: 'Sử dụng ở đâu ; Sử dụng tạm thời; Sử dụng filesort '-

Dưới đây là toàn bộ kết quả của GIẢI THÍCH:

  • id: '1'
  • select_type: 'đơn giản'
  • bảng: ''
  • loại:' sự kiện ref '
  • possible_keys: 'index_campaign, idx_campaignid_paid, idx_city_country_code, idx_city_country_code_campaign_id, idx_cid, idx_campaign_id_city_country_code'
  • chính:' idx_campaign_id_city_country_code '
  • key_len: '4'
  • ref: 'const'
  • hàng: '471.304'
  • Extra:' Sử dụng ở đâu; Sử dụng tạm thời; Sử dụng filesort'

UPDATE:

Ok, tôi nghĩ rằng nó đã được giải quyết:

Nhìn vào truy vấn dán ở đây một lần nữa tôi nhận ra rằng tôi quên đề cập đến ở đây là đã có thêm một cột trong SELECT được gọi là 'country_name'. Vì vậy, truy vấn rất chậm sau đó (bao gồm cả country_name), nhưng tôi sẽ chỉ để nó ra và bây giờ hiệu suất của truy vấn là hoàn toàn ok. Xin lỗi vì sai lầm đó!

Cảm ơn tất cả các nhận xét hữu ích của bạn, tôi sẽ nêu lên tất cả các câu trả lời hay! Có một số bổ sung thực sự hữu ích, mà tôi cũng có thể chúng tôi áp dụng (như thay đổi các loại vv).

+0

gì giải thích SELECT COUNT (*) AS counted_events, mã quốc gia TỪ ĐÂU sự kiện campaign_id' tại (597) GROUPY THEO thành phố, mã quốc gia ORDER BY counted_events cho? – sathia

+0

'Giải thích' cho thấy rằng trong số nhiều chỉ mục có thể MySql sử dụng chỉ mục này: 'idx_campaign_id_city_country_code', cho các hàng hiển thị: '471304' và đối với 'Phụ trang', nó hiển thị: 'Sử dụng vị trí; Sử dụng tạm thời; Sử dụng filesort ' – user3767671

+0

Cái ác ở đây là 'ORDER BY counting_events' đang gây ra' Sử dụng tạm thời; Sử dụng filesort '' –

Trả lời

0

không sử dụng IN() - sử dụng tốt hơn:

WHERE campaign_id = 597 
OR campaign_id = 231 
OR .... 

afaik IN() là rất chậm.

update: như nik0lias nhận xét - IN() nhanh hơn concatenating OR điều kiện.

+0

Sau đó, bạn đã sai. Có rất nhiều bằng chứng rằng IN thực sự nhanh hơn. Đây chỉ là một câu hỏi ..http: //stackoverflow.com/questions/782915/mysql-or-vs-in-performance – nik0lias

+0

Đối với '25.000.000 hàng nhiều' hoặc' không hoạt động ngay cả với các cột được lập chỉ mục. –

+1

@ nik0lias, ok - vậy thì tôi sai rồi. –

3

mà không nhìn thấy những gì GIẢI THÍCH nói đó là một cú sút xa từ lâu, dù sao:

  1. làm một chỉ mục trên (thành phố, COUNTRY_CODE)
  2. xem nếu có một cách sử dụng phân vùng, bảng của bạn là nhận được khá lớn
  3. nếu mã quốc gia luôn luôn là 2 ký tự thay đổi nó để char
  4. thay đổi chỉ số số để unsigned int

p ost toàn bộ sản lượng GIẢI THÍCH

+0

Tôi đã cập nhật câu hỏi để phản ánh toàn bộ kết quả EXPLAIN – user3767671

+1

vui lòng định dạng đầu ra của bạn và cũng thêm lược đồ thực tế cho bảng. thật khó để giúp đỡ cách khác – sathia

+0

thêm đầu ra của "hiển thị tạo sự kiện bảng" – sathia

0

Một số ý tưởng:

  • Do tính chất và kích thước của bảng nó sẽ là một ứng cử viên tuyệt vời cho partitioned tables theo quốc gia. Bằng cách này, các sự kiện của mọi quốc gia sẽ được lưu trữ trong một bảng vật lý khác ngay cả khi nó hoạt động như một bảng lớn ảo

  • Mã quốc gia có phải là một chuỗi không? Có thể bạn có một country_id có thể sắp xếp dễ dàng hơn. (Nó có thể buộc bạn tạo hoặc thay đổi chỉ mục)

  • Bạn có thực sự sử dụng thành phố trong nhóm không?

0
  • phân vùng - đặc biệt là bởi đất nước sẽ không giúp đỡ
  • cột IN (const-list) là không làm chậm, nó thực chất là một trường hợp với tối ưu hóa đặc biệt

Vấn đề là, MySQL không sử dụng chỉ mục để sắp xếp. Tôi không thể nói tại sao, bởi vì nó nên. Có thể là một lỗi.

Chiến lược tốt nhất để thực hiện truy vấn này là quét cây con của chỉ mục trong đó event_id = 597. Vì chỉ mục sau đó được sắp xếp theo city_id, country_code không cần phân loại thêm và các hàng có thể được đếm trong khi quét.

Vì vậy, các chỉ mục đã tối ưu cho truy vấn này. MySQL không chỉ sử dụng chúng một cách chính xác.


Tôi đang nhận được nhiều thông tin hơn ngoài dòng. Dường như đây không phải là vấn đề cơ sở dữ liệu chút nào, nhưng

  1. giản đồ này không được chuẩn hóa. Bảng này không chỉ chứa country_code, mà còn cả country_name (điều này sẽ nằm trong một bảng phụ).
  2. yêu cầu thực chứa tên miền quốc gia trong danh sách chọn. Nhưng vì cột đó không được lập chỉ mục, nên MySQL không thể sử dụng quét chỉ mục.

Ngay sau khi tên miền quốc gia bị xóa khỏi danh sách chọn, truy vấn sẽ trở về quét chỉ mục ("sử dụng chỉ mục" trong đầu ra EXPLAIN) và nhanh quá nhanh.

+0

Cảm ơn tất cả mọi người! – user3767671

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