Cách tốt nhất để CHỌN một tập dữ liệu lớn vào cơ sở dữ liệu MySQL (hoặc bất kỳ cơ sở dữ liệu nào nói chung)


9

Là một phần của dự án PHP, tôi phải chèn một hàng vào cơ sở dữ liệu MySQL. Tôi rõ ràng đã quen với việc này, nhưng yêu cầu này phải chèn vào 90 cột trong một truy vấn. Truy vấn kết quả trông khủng khiếp và nguyên khối (đặc biệt là chèn các biến PHP của tôi làm giá trị):

INSERT INTO mytable (column1, colum2, ..., column90) 
VALUES
('value1', 'value2', ..., 'value90')

và tôi lo ngại rằng tôi sẽ không làm điều này theo cách đúng đắn. Tôi cũng mất một thời gian dài (nhàm chán) chỉ để gõ mọi thứ vào và kiểm tra viết mã kiểm tra cũng sẽ tẻ nhạt không kém tôi sợ.

Làm thế nào để các chuyên gia đi nhanh chóng viết và kiểm tra các truy vấn này? Có cách nào để tôi có thể tăng tốc quá trình không?


2
Tôi lo ngại rằng bảng có 90 cột hơn lượng thời gian không đáng kể để nhập tên cột. (BTW Tôi kéo và thả tất cả các cột cùng một lúc trong SQL Server, không có nơi nào để làm điều tương tự trong myQuery hoặc PHP? Tôi sẽ xem liệu bạn có thể thấy rằng nó làm cho cuộc sống dễ dàng hơn vì không có lỗi chính tả.)
HLGEM

1
Tôi biết 90 cột là rất nhiều, nhưng mỗi cột liên quan đến một trường duy nhất cho một tài liệu pdf mà tôi cần phải điền và tôi không thấy điểm nào trong việc phá vỡ nó, hoặc tôi sẽ làm như thế nào. Cảm ơn thông tin về SQL Server. Tôi không chắc ý của bạn về việc kéo và thả các cột mà tôi sẽ xem xét.
Joe

1
Viết một câu lệnh chọn liệt kê tất cả các cột trong một bảng đã cho và đi từ đó.
JeffO

Jeff O: Tôi cũng đã sử dụng nó, nó có thể là một kỹ thuật rất mạnh nếu được thực hiện đúng. Bạn nên đăng nó như một câu trả lời nếu bạn có thể đưa ra một ví dụ mã!
Thất vọngWithFormsDesigner

Câu trả lời:


7

Joe, bình luận cuối cùng của bạn giải thích rất nhiều. Tôi nghĩ vấn đề thực sự là thiết kế dữ liệu. Các cột mới có thể cần thiết khi định dạng tài liệu thay đổi và theo kinh nghiệm của tôi, các định dạng tài liệu có xu hướng thay đổi thường xuyên. Thay vì một bảng 90 cột, với một hàng cho mỗi báo cáo, tôi sẽ lưu trữ dữ liệu báo cáo trong một bảng có bốn cột: report_id, format_id, field_name, field_value. Mỗi báo cáo sẽ được đại diện bởi 90 hàng, một hàng cho mỗi giá trị trường trong báo cáo. Điều này sẽ đơn giản hóa mã của bạn đáng kể.


Cảm ơn vì đã trả lời. Tất cả các trường (ngoài chỉ mục) là VARCHARS, do đó, nó sẽ hoạt động với tôi (và dù sao tôi cũng có thể chuyển đổi các giá trị khác). Tôi có thể lãng phí rất nhiều dung lượng mặc dù vì tôi phải đặt kích thước của cột field_value thành giá trị lớn nhất (dài khoảng 256 ký tự) trong khi một số trường chỉ yêu cầu độ dài 3. Chắc chắn sẽ dễ sử dụng hơn và tôi có thể hiểu làm thế nào nó sẽ là bằng chứng trong tương lai nhiều hơn như bạn mô tả.
Joe

4
FWIW, hầu hết các hệ thống cơ sở dữ liệu chỉ sử dụng nhiều dung lượng theo yêu cầu để lưu trữ dữ liệu. Vì vậy, nếu bạn chỉ lưu trữ 3 ký tự trong trường VARCHAR (256), nó sẽ chỉ mất 3 byte chứ không phải 256. Tôi không biết nhiều về các phần bên trong của MySQL, nhưng tôi sẽ ngạc nhiên nếu họ đệm toàn bộ các trường của họ kích thước khai báo.
TMN

@TMN Đó là ý nghĩa của VAR trong VARCHAR! Biến chiều dài Char. Đây là một hàm (hoặc định nghĩa) của kiểu Dữ liệu chứ không phải hệ thống DB. Cũng không phải là vì VARCHAR là Độ dài biến, DB cần biết độ dài cho mỗi giá trị, do đó, nó lưu trữ độ dài dưới dạng siêu dữ liệu. Điều đó có nghĩa là lưu trữ trên cao! Vì vậy, một VARCHAR (1) thực sự sử dụng 3 byte dữ liệu vì chi phí hoạt động, gấp 3 lần so với Char (1)!
Morons

2
-1, tôi không đồng ý với câu trả lời này, Trong trường hợp này, bạn tốt hơn với 90 cột. Nếu thực thể có 90 điểm dữ liệu, thì cũng vậy, hãy giữ dữ liệu của bạn hợp lý.
Morons

@TMN chỉ để làm rõ quan điểm của tôi, cho biết "Vì vậy, nếu bạn chỉ lưu trữ 3 ký tự trong trường VARCHAR (256), nó sẽ chỉ mất 3 byte" Sự thật là nó sẽ chiếm 5 byte chứ không phải 3
Morons

7

Nói chung, cách nhanh nhất để tải một tập dữ liệu lớn vào cơ sở dữ liệu SQL là sử dụng giao diện tải hàng loạt riêng. Theo như tôi biết, mỗi dbms SQL có ít nhất một.

Tài liệu MySQL: Sử dụng Trình tải hàng loạt

Nếu tôi phải biến một tệp được phân tách bằng dấu phẩy hoặc dấu phẩy thành các câu lệnh SQL INSERT, tôi sử dụng awk để đọc tệp đầu vào và ghi tệp đầu ra. Không có gì thực sự đặc biệt về awk; nó chỉ là ngôn ngữ xử lý văn bản mà tôi biết rõ nhất. Bạn có thể nhận được kết quả tương tự bằng cách viết mã bằng Perl, Python, Ruby, Rexx, Lisp, v.v.


2
Tải hàng loạt thực sự là cách để đi nếu bạn cần chèn một số lượng lớn các hàng, nhưng trong trường hợp này, anh ta chỉ cần chèn một hàng duy nhất với nhiều cột. Tải số lượng lớn sẽ không giúp ích và có thể sẽ yêu cầu viết nhiều mã hơn so với cách tiếp cận đơn giản.
TMN

-1, câu trả lời này hoàn toàn thiếu điểm của câu hỏi
Doc Brown

2

Nếu bạn có thể dễ dàng lấy tên cột vào bảng tính Excel, bạn có thể viết macro Excel để tạo mã cho các truy vấn và câu lệnh DML khác nhau, sau đó chỉ cần dán giá trị vào cột khác và câu lệnh chèn / cập nhật của bạn được tạo tự động cho bạn. Gõ thủ công là một cách rất chậm để làm điều đó, vì vậy hãy xem liệu bạn có thể tìm thấy các thủ thuật bằng cách sử dụng các công cụ hiện có của mình không. Nhiều trình soạn thảo văn bản theo định hướng của nhà phát triển cũng có khả năng ghi và lưu trữ các macro để thực hiện các công việc lặp đi lặp lại như thế này nhanh hơn và dễ dàng hơn.


2

Nếu bạn có tệp csv, bạn có thể sử dụng LOAD DATA INFILE ... để nhập dữ liệu.

Nếu bạn phải sử dụng các truy vấn 'INSERT', thì thực hiện chèn số lượng lớn sẽ tăng tốc quá trình. Thay vì chạy truy vấn 'INSERT' cho mỗi hàng đơn lẻ, hãy nhóm các hàng, nói 100 và chạy truy vấn. Một cái gì đó như thế này:

INSERT INTO theTable (col1, col2, col3,....., col89, col90) 
VALUES
(val11, val12, val13, ........, val189, val190),
(val21, val22, val23, ........, val289, val290),
.......
......
(val101, val102, val103, ........, va1089, val1090);

2

Một cách hiệu quả để ghi dữ liệu truy vấn nhiều cột vào MySQL DB là chuyển đổi các dữ liệu này thành định dạng JSON hoặc YAML và chèn chúng dưới dạng một đơn vị. Nó thay đổi "ghi một phần chèn cho một bảng có 90 cột" thành "ghi một phần chèn vào một bảng có một cột".

Theo cách tiếp cận này, không phải mọi thứ cần được chia thành các thành phần cơ bản của nó và mốc dữ liệu duy nhất được lưu trữ chỉ trong 1 cột.


@gnat: nó cung cấp một giải pháp thay thế. Nó thay đổi "ghi một phần chèn cho một bảng có 90 cột" thành "ghi một phần chèn vào một bảng có một cột". Đưa ra vấn đề như mô tả, nó là một giải pháp hợp lệ. Không phải mọi thứ cần được chia thành các thành phần cơ bản của nó. Câu trả lời tương tự khác, được đề xuất là sẽ hoàn thành NoQuery, loại bỏ hoàn toàn cơ sở dữ liệu SQL, điều này là quá mức cần thiết. Câu trả lời này nói rằng bạn có thể sử dụng một cách tiếp cận hỗn hợp. Chỉ cần 1 cột cho mốc này. Hãy xem xét rằng giải pháp thay thế có thể là có một cột nhị phân và lưu trữ toàn bộ pdf.
jmoreno

@gnat: Tôi sẽ cho Noviff cơ hội để nói điều đó bằng lời nói của mình ...
jmoreno

@ gnat và jmoreno - cảm ơn bạn đã bình luận. Tôi thích làm rõ câu trả lời của gnat và tôi đã chỉnh sửa câu trả lời dựa trên sự làm rõ của anh ấy.
17:54

0

Với MySQL, bạn có thể sử dụng cú pháp thay thế cho các insertcâu lệnh:

insert into table
        set column1 = value1
          , column2 = value2
          , column3 = value3

1
Đây thực sự là nhanh hơn?
Pacerier

@Pacerier Không, cái này không nhanh hơn. Chỉ cần một cú pháp khác.
Muffars cho phép

0

Kịch bản của bạn có vẻ phù hợp rất tốt cho giải pháp NoQuery, vì danh sách thuộc tính có thể thay đổi bất cứ khi nào định dạng thay đổi. Bạn đã đánh giá các tùy chọn khác ngoài MySQL chưa? Tìm hiểu về DynamoDB / MongoDB / Cassandra - có thể phù hợp hơn.


-1

Có cách hiệu quả hơn để chèn dữ liệu vào cơ sở dữ liệu bằng cách sử dụng php và mysql. Chúng ta có thể sử dụng LOAD HÀNH để chèn dữ liệu. Nó chèn dữ liệu nhanh đáng kể.

Đối với điều này, hãy tạo một tệp phẳng (ví dụ: tôi đã sử dụng tệp .csv) với dữ liệu của bạn bằng fputcsv()chức năng. Sau đó chèn dữ liệu bằng lệnh LOAD. Cú pháp một số thứ tương tự như dưới đây:

LOAD DATA LOCAL INFILE "C:/downloads/local/my_data_file.csv"
INTO TABLE  my_data
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\r\n'
IGNORE 1 LINES;

-1

Hãy thử như sau. Đã làm cho tôi.

Tên biểu mẫu phải bằng tên cột cơ sở dữ liệu

Lấy các giá trị như dưới đây:

foreach ($_GET as $formName => $value) {
    $sql = mysql_query("UPDATE table_name SET $formName = '$value' WHERE ID= $id");
}

Trước tiên bạn sẽ cần chèn ID trước vòng lặp foreach. bạn có thể lấy id tiếp theo bằng cách thực hiện:

SELECT MAX(id) FROM .....

thêm 1 vào id và chèn nó.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.