2012-03-14 50 views
6

Tôi có một bảng có 300 000 bản ghi. Trong bảng này có duplicae hàng và tôi muốn cập nhật cột "lá cờ"Làm cách nào để tối ưu hóa truy vấn MySQL để cập nhật?

TABLE

------------------------------------ 
|number | flag | ... more column ...| 
------------------------------------ 
|ABCD | 0 | ...................| 
|ABCD | 0 | ...................| 
|ABCD | 0 | ...................| 
|BCDE | 0 | ...................| 
|BCDE | 0 | ...................| 

tôi sử dụng truy vấn này để cập nhật "cờ" cột:

UPDATE table i 
INNER JOIN (SELECT number FROM table 
      GROUP BY number HAVING count(number) > 1) i2 
ON i.number = i2.number 
SET i.flag = '1' 

Truy vấn này làm việc rất rất từ từ (hơn 600 giây) cho 300 000 bản ghi này.

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

cấu trúc của bảng MY

CREATE TABLE IF NOT EXISTS `inv` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `pn` varchar(10) NOT NULL COMMENT 'Part Number', 
    `qty` int(5) NOT NULL, 
    `qty_old` int(5) NOT NULL, 
    `flag_qty` tinyint(1) NOT NULL, 
    `name` varchar(60) NOT NULL, 
    `vid` int(11) NOT NULL , 
    `flag_d` tinyint(1) NOT NULL , 
    `flag_u` tinyint(1) NOT NULL , 
    `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
    PRIMARY KEY (`id`), 
    KEY `pn` (`pn`), 
    KEY `name` (`name`), 
    KEY `vid` (`vid`), 
    KEY `pn_2` (`pn`), 
    KEY `flag_qty` (`flag_qty`) 
) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=0 ; 

Nếu "tên" là lặp lại tôi muốn cập nhật flag_qty

+0

Cấu trúc bảng là gì? Có một khóa chính có sẵn trên bảng này không? – nnichols

+1

Mục đích của việc thiết lập cờ này là gì? Bạn đang làm một số xử lý tiếp theo dựa trên lá cờ này? – nnichols

+0

Mục đích trên lá cờ này là IF có trong các hàng trùng lặp của bảng, cờ này là 1. Sau đó tôi muốn tạo bảng có các hàng trùng lặp và xóa các hàng này khỏi bảng chính. – dido

Trả lời

2

Nếu bạn chưa có một chỉ mục trên number bạn nên thêm một -

CREATE INDEX table_number ON table (number); 

CẬP NHẬT Hãy thử điều này -

UPDATE inv t1 
INNER JOIN inv t2 
    ON t1.name = t2.name 
    AND t1.id <> t2.id 
SET t1.flag_qty = 1; 

Bạn có thể tạo bảng của bạn chỉ với các bản sao bằng cách chọn dữ liệu này trực tiếp vào một bảng khác thay vì thực hiện cập nhật cờ này trước tiên.

INSERT INTO duplicate_invs 
SELECT DISTINCT inv1.* 
FROM inv AS inv1 
INNER JOIN inv AS inv2 
    ON inv1.name = inv2.name 
    AND inv1.id < inv2.id 

Nếu bạn có thể giải thích được toàn bộ quá trình có thể được thực hiện trong một bước.

+0

số cột là INDEX – dido

+0

Trong trường hợp đó, vui lòng đăng đầu ra của 'HIỂN THỊ INDEXES FROM table_name'. Tôi chạy truy vấn của bạn đối với hàng 3M trong một thử nghiệm và nó trở lại chỉ hơn 1s trên máy tính xách tay của tôi. Việc thêm cấu trúc bảng đầy đủ (đầu ra từ 'SHOW CREATE TABLE table_name') có thể hữu ích. – nnichols

+0

Tôi đã thêm cấu trúc sql của bảng. – dido

1

Nhận MySQL để EXPLAIN truy vấn cho bạn. Sau đó, bạn sẽ thấy những gì chỉ mục sẽ cải thiện mọi thứ.

1

EXPLAIN sẽ cho bạn thấy nơi nó là chậm và here're một số ý tưởng, cách để cải thiện hiệu suất hoạt:

  • Thêm indexing
  • Sử dụng InnoDB phím nước ngoài
  • Chia truy vấn vào 2 và xử lý chúng một cách riêng biệt trong lagnuage bạn sử dụng.
  • viết cùng một ý tưởng trong thủ tục MySQL (không chắc chắn, cho dù điều này sẽ được nhanh chóng).
1

Tôi sẽ sử dụng bảng tạm thời. 1.) chọn tất cả các bản ghi có liên quan vào bảng tạm thời, đặt INDEX trên id. 2.) cập nhật bảng bằng cách sử dụng một cái gì đó như thế này

UPDATE table i, tmp_i 
SET i.flag = '1' 
WHERE i.id = tmp_i.id 
1

bạn có thể thử (giả sử VB.net, nhưng có thể được thực hiện với bất kỳ ngôn ngữ nào).

Dim ids As String = Cmd.ExectueScalar("select group_concat(number) from (SELECT number FROM table GROUP BY number HAVING count(number) > 1)") 

Sau khi bạn nhận được danh sách các ID (dấu phẩy phân cách) vì sử dụng

UPDATE i 
SET i.flag = '1' 
WHERE i.number in (....) 

Nó có thể được làm chậm cũng có, nhưng người đầu tiên - SELECT, sẽ không bị khóa cơ sở dữ liệu và sao chép của bạn, vv . UPDATE sẽ nhanh hơn.

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