2008-11-29 32 views
5

Tôi có một trang PHP cụ thể, vì nhiều lý do, cần lưu ~ 200 trường vào cơ sở dữ liệu. Đây là 200 câu lệnh chèn và/hoặc cập nhật riêng biệt. Bây giờ điều hiển nhiên là làm giảm số lượng này nhưng, như tôi đã nói, vì những lý do tôi sẽ không bận tâm đến việc tôi không thể làm điều này.Làm cách nào để triển khai bộ nhớ đệm ghi đè nền/không đồng bộ trong PHP?

Tôi đã không mong đợi vấn đề này. Lựa chọn có vẻ có hiệu quả hợp lý trong MySQL nhưng chèn/cập nhật không (mất khoảng 15-20 giây để thực hiện cập nhật này, điều này hoàn toàn không thể chấp nhận được). Tôi đã viết các hệ thống Java/Oracle có thể thực hiện hàng ngàn lần chèn/cập nhật một cách vui vẻ (trong cả hai trường hợp chạy cơ sở dữ liệu cục bộ; MySQL 5 so với OracleXE).

Bây giờ trong một cái gì đó giống như Java hay Net tôi có thể khá dễ dàng làm một trong các cách sau:

  1. Viết dữ liệu vào một trong bộ nhớ ghi-đằng sau bộ nhớ cache (tức là nó sẽ biết làm thế nào để tồn tại vào cơ sở dữ liệu và có thể làm như vậy một cách không đồng bộ);
  2. Ghi dữ liệu vào bộ nhớ cache trong bộ nhớ và sử dụng mô hình PaaS (Persistence as a Service) tức là người nghe đến bộ nhớ cache sẽ tiếp tục tồn tại các trường; hoặc
  3. Chỉ cần bắt đầu quá trình nền có thể duy trì dữ liệu.

Giải pháp tối thiểu là có bộ nhớ cache mà tôi có thể cập nhật, sẽ tự động truy cập cơ sở dữ liệu theo thời gian riêng (tức là nó sẽ trở lại ngay sau khi cập nhật bộ nhớ đệm trong bộ nhớ). Điều này có thể là bộ đệm ẩn toàn cục hoặc bộ nhớ cache phiên (mặc dù bộ nhớ cache được chia sẻ chung có kháng cáo theo các cách khác).

Bất kỳ giải pháp nào khác cho loại vấn đề này?

Trả lời

1

Bạn sẽ có thể thực hiện 200 lần chèn tương đối nhanh, nhưng nó sẽ phụ thuộc vào nhiều yếu tố. Nếu bạn đang sử dụng một công cụ giao dịch và thực hiện từng giao dịch trong giao dịch của chính nó, đừng - điều đó tạo ra quá nhiều I/O.

Nếu bạn đang sử dụng một công cụ phi giao dịch, điều này sẽ phức tạp hơn một chút. Sử dụng một chèn nhiều hàng đơn có khả năng tốt hơn vì chính sách xả của MySQL có nghĩa là nó sẽ không cần phải tuôn ra các thay đổi của nó sau mỗi hàng.

Bạn thực sự muốn có thể tái tạo điều này trên hộp phát triển sản xuất-spec của bạn và phân tích chính xác lý do tại sao nó xảy ra. Nó không phải là khó khăn để dừng lại. Tất nhiên một khả năng khác là chèn của bạn chậm vì các bảng có kích thước cực lớn hoặc số lượng lớn các chỉ mục - trong trường hợp đó bạn nên mở rộng quy mô máy chủ cơ sở dữ liệu của mình một cách thích hợp. Chèn rất nhiều hàng vào một bảng có chỉ mục không phù hợp với RAM (hoặc không có RAM cấu hình chính xác để được sử dụng cho bộ nhớ đệm những chỉ mục) thường được khá mùi.

NHƯNG đừng cố gắng tìm cách làm phức tạp ứng dụng của bạn khi có cách dễ dàng điều chỉnh ứng dụng thay vì giữ thuật toán hiện tại.

+1

Bit "tối ưu hóa sớm" là lời khuyên tốt. Các bảng không quá phức tạp nhưng tôi có một vài điều tôi có thể kiểm tra ngay bây giờ (chỉ mục và cơ sở dữ liệu). – cletus

+0

làm cách nào để trả lời câu hỏi liên quan đến chèn không đồng bộ? – nightograph

1

Bạn có thể cập nhật bộ nhớ cache cục bộ của mình (hy vọng được ghi nhớ) và sau đó đẩy yêu cầu ghi thông qua beanstalkd.

+0

Cảm ơn câu trả lời của bạn. Tôi đã có một cái nhìn và có rất nhiều bộ phận chuyển động: memcached, beanstalkd và giả định một cái gì đó khác để đọc hàng đợi công việc và lưu giữ dữ liệu? – cletus

+0

Đó là chính xác. Các phần thực sự * đơn giản, mặc dù và cho phép bạn mở rộng quy mô ứng dụng của mình. Bạn sẽ thấy mình muốn đặt nhiều thứ hơn thông qua các công nhân (chẳng hạn như gửi email, cập nhật công cụ tìm kiếm, v.v.). memcached là trực giao, nhưng nên ở khắp mọi nơi anyway. – Dustin

+0

Bất kỳ đề xuất nào về những gì cần sử dụng cho quá trình nền? Một cái gì đó sẽ cần phải đọc từ hàng đợi công việc và xử lý các yêu cầu. Tôi đã nhìn thấy một số blog về những người sử dụng Ruby với beanstalkd, có thể cả Java nữa. Tôi không quan tâm đến việc có một máy chủ trong hỗn hợp mặc dù. – cletus

0

Tôi nghi ngờ có vấn đề với chèn SQL của bạn - nó thực sự không nên mất nhiều thời gian. Các truy vấn được chuẩn bị có giúp ích không? Máy chủ mysql của bạn có cần thêm bộ nhớ dành riêng cho keyspace không? Tôi nghĩ rằng một số câu hỏi khác cần được hỏi.

0

How are you làm việc chèn, bạn đang làm một chèn cho mỗi bản ghi

mysql_query('INSERT INTO tableName VALUES(...)'); 
mysql_query('INSERT INTO tableName VALUES(...)'); 
mysql_query('INSERT INTO tableName VALUES(...)'); 
mysql_query('INSERT INTO tableName VALUES(...)'); 
mysql_query('INSERT INTO tableName VALUES(...)'); 

hoặc bạn đang sử dụng một truy vấn đơn

mysql_query('INSERT INTO tableName VALUES(...),(...),(...),(...)'); 

Các sau trong hai tùy chọn là nhanh hơn đáng kể, và từ trải nghiệm tùy chọn đầu tiên sẽ khiến nó mất nhiều thời gian hơn vì PHP phải chờ truy vấn đầu tiên kết thúc trước khi chuyển sang thứ hai và tiếp tục như vậy.

+0

Mỗi cập nhật trường là bản cập nhật nếu nó đã tồn tại hoặc chèn nếu không. Tôi đã biết nếu nó tồn tại hay không bởi vì tôi đã cài đặt sẵn tất cả các giá trị. Điều này sẽ giải quyết vấn đề chèn rộng nhưng các sửa đổi là và sẽ được cập nhật chủ yếu. – cletus

+1

cletus bạn có thể sử dụng UNIQUE INDEX trong cơ sở dữ liệu và ON UPPLING DUPLICATE KEY trong các truy vấn của bạn để giải quyết vấn đề đó bằng cách sử dụng giải pháp này. Google cho nó :) –

1

Xem thống kê cho cơ sở dữ liệu của bạn trong khi bạn thực hiện chèn. Tôi đang đoán rằng một trong các cập nhật của bạn sẽ khóa bảng và do đó tất cả các câu lệnh của bạn được xếp hàng đợi và bạn gặp phải sự chậm trễ này. Một điều cần xem xét là tạo/cập nhật chỉ mục của bạn vì bạn có nhiều chỉ mục hơn trên bảng, tất cả các câu lệnh UPDATEINSERT đều nhận được.

Một điều nữa là tôi nghĩ bạn sử dụng MYISAM (công cụ bảng) khóa toàn bộ bảng trên UPDATE.Thay vào đó, tôi khuyên bạn nên sử dụng INNODB. INNODB chậm hơn trên SELECT truy vấn, nhưng nhanh hơn trên INSERTUPDATE bởi vì nó chỉ khóa hàng mà nó đang hoạt động chứ không phải toàn bộ bảng.

+0

Tổng quá trình đơn giản hóa (và có thể không chính xác) về đặc tính hiệu suất của động cơ mysql. Khóa toàn bộ bảng có thể nhanh hơn so với khóa các hàng (vì chỉ có một khóa để thực hiện). – MarkR

+0

Cái gì? MYISAM khóa toàn bộ bảng, do đó làm cho ghi không có sẵn trong khóa, dẫn đến một tồn đọng lớn (= chậm trễ). Innodb chỉ khóa hàng mà nó đang hoạt động - các quy trình khác vẫn có thể viết trên bàn. – Till

2

Một giải pháp khác mà bạn có thể sử dụng (thay vì điều chỉnh mysql :)) là sử dụng một số máy chủ JMS và STOMP connection driver cho PHP để ghi dữ liệu vào máy chủ cơ sở dữ liệu theo cách không đồng bộ. ActiveMQ có hỗ trợ tích hợp cho giao thức STOMP. Và có dự án StompConnect là proxy STOMP cho bất kỳ máy chủ biên dịch JMS nào (OpenMQ, JBossMQ, v.v.).

+0

Ngoài ra OpenMQ, một phần của máy chủ ứng dụng GlassFish (nhưng cũng có thể chạy mà không có nó) là một máy chủ JMS sẽ hỗ trợ Stomp trong phiên bản 4.4 – mjn

2

mysql_query ('INSERT INTO tableName GIÁ TRỊ (...), (...), (...), (...)')

Trên tuyên bố truy vấn cụ thể là tốt hơn. Nhưng chúng tôi có một giải pháp khác để cải thiện hiệu suất của lệnh chèn.Thực hiện theo các bước sau .. 1. Bạn chỉ cần tạo tệp csv (dấu phân tách bằng dấu phẩy) hoặc tệp txt đơn giản và ghi tất cả dữ liệu bạn muốn chèn bằng cách ghi tệp machanism (như lớp FileOutputStream trong java). 2. sử dụng lệnh này

LOAD DATA INFILE 'data.txt' INTO TABLE table2 FIATDS TERMINATED BY '\ t';

3 nếu bạn không hiểu rõ về lệnh này sau đó làm theo các liên kết đưa ra dưới đây

http://dev.mysql.com/doc/refman/5.1/en/load-data.html

0

xem xét việc này:

mysql_query('start transaction'); 
mysql_query('INSERT INTO tableName VALUES(...)'); 
mysql_query('INSERT INTO tableName VALUES(...)'); 
mysql_query('INSERT INTO tableName VALUES(...)'); 
mysql_query('INSERT INTO tableName VALUES(...)'); 
mysql_query('INSERT INTO tableName VALUES(...)'); 
mysql_query('commit;') 
+0

Điều này làm cho truy vấn trong nền như thế nào? –

0

bạn có thể sử dụng CURL với PHP để làm thao tác cơ sở dữ liệu không đồng bộ.

Một giải pháp có thể là chia từng truy vấn thành một chuỗi riêng biệt nhưng PHP không hỗ trợ chủ đề. Chúng tôi có thể sử dụng các chức năng PCNTL nhưng hơi khó để tôi sử dụng chúng. Tôi thích sử dụng giải pháp này để tạo ra ngã ba và thực hiện các hoạt động không đồng bộ.

Tham khảo này

http://gonzalo123.wordpress.com/2010/10/11/speed-up-php-scripts-with-asynchronous-database-queries/

1

Lưu ý rằng nếu bảng của bạn là INSERT-CHỈ (không xóa, và không có thông tin cập nhật trên các cột chiều dài thay đổi), sau đó chèn sẽ không khóa hoặc khối đọc khi sử dụng MyISAM.

Điều này có thể hoặc không thể cải thiện hiệu suất chèn, nhưng nó có thể giúp đỡ nếu bạn đang gặp vấn đề chèn/đọc đồng thời.

Tôi đang sử dụng tính năng này và chỉ thanh toán các bản ghi cũ hàng ngày, tiếp theo là 'tối ưu hóa bảng'.

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