2009-04-25 59 views
12

Tôi có một cơ sở dữ liệu Sqlite3 với một bảng và một khóa chính bao gồm hai số nguyên, và tôi đang cố chèn nhiều dữ liệu vào nó (ví dụ: khoảng 1GB hoặc hơn)Sqlite3: Vô hiệu hóa chỉ mục khóa chính khi chèn?

Vấn đề tôi gặp phải là tạo khóa chính cũng ngầm tạo ra một chỉ mục, trong trường hợp của tôi bogs xuống chèn vào một thu thập thông tin sau một vài cam kết (và đó là vì tệp cơ sở dữ liệu nằm trên NFS .. sigh).

Vì vậy, tôi muốn bằng cách nào đó tạm thời vô hiệu hóa chỉ mục đó. Kế hoạch tốt nhất của tôi cho đến nay liên quan đến việc giảm chỉ số tự động của khóa chính, tuy nhiên có vẻ như SQLite không thích nó và ném một lỗi nếu tôi cố gắng làm điều đó.

Kế hoạch tốt nhất thứ hai của tôi sẽ liên quan đến ứng dụng tạo bản sao trong suốt của cơ sở dữ liệu trên ổ đĩa mạng, thực hiện sửa đổi và sau đó hợp nhất lại. Lưu ý rằng trái ngược với hầu hết các câu hỏi SQlite/NFS, tôi không cần truy cập đồng thời.

Điều gì sẽ là một cách chính xác để làm điều gì đó như vậy?

UPDATE:

Tôi quên để xác định cờ Tôi đã sử dụng:

PRAGMA synchronous = OFF 
PRAGMA journal_mode = OFF 
PRAGMA locking_mode = EXCLUSIVE 
PRAGMA temp_store = MEMORY 

UPDATE 2: tôi trên thực tế cách chèn mục theo lô, tuy nhiên mỗi tiếp theo hàng loạt là chậm hơn để cam kết hơn trước đó (tôi giả định này đã làm với kích thước của chỉ số). Tôi đã cố gắng làm các lô từ 10k đến 50k tuple, mỗi một là hai số nguyên và một phao.

Trả lời

10
  1. Bạn không thể xóa chỉ mục được nhúng vì đó là địa chỉ duy nhất của hàng.
  2. Hợp nhất 2 khóa nguyên của bạn bằng một khóa dài = (key1 < < 32) + key2; và thực hiện điều này một KEY INTEGER PRIMARY schema youd (trong trường hợp đó bạn sẽ chỉ có 1 index)
  3. Đặt kích thước trang cho DB mới ít nhất 4096
  4. loại bỏ bất kỳ chỉ số bổ sung trừ chính
  5. Điền vào dữ liệu trong thứ tự SORTED để khóa chính đang phát triển.
  6. lệnh Tái sử dụng, không tạo ra mỗi lần chúng từ chuỗi
  7. Đặt kích thước trang bộ nhớ cache vào bộ nhớ nhiều như bạn đã để lại (nhớ rằng kích thước bộ nhớ cache là số lượng trang, nhưng không phải số byte)
  8. Cam kết mỗi 50000 mục.
  9. Nếu bạn có chỉ số bổ sung - tạo ra chúng chỉ sau khi tất cả dữ liệu trong bảng

Nếu bạn sẽ có thể sáp nhập key (Tôi nghĩ rằng bạn đang sử dụng 32bit, trong khi SQLite sử dụng 64bit, vì vậy nó có thể) và điền dữ liệu theo thứ tự sắp xếp Tôi đặt cược bạn sẽ điền vào Gb đầu tiên của bạn với hiệu suất tương tự như thứ hai và cả hai sẽ đủ nhanh.

+0

Giữ lượng dữ liệu trên một INSERT tuyên bố trong kiểm tra với tham số cache_size dường như làm các trick. Rõ ràng là có nhiều bộ nhớ đệm hơn, nhiều mục hơn có thể được chèn vào trong một lần. Ngoài ra có vẻ như tôi chỉ có thể thực hiện một cam kết ở cuối tất cả mọi thứ sau khi tất cả. –

+0

Vâng, bạn có thể. Nhưng thủ thuật chính cho bất kỳ hoạt động chèn nào là O (1) là điền dữ liệu được sắp xếp theo chỉ mục đó, nhưng trong trường hợp dữ liệu của bạn phù hợp với bộ nhớ cache, mọi thứ đều rất nhanh. Đó là hợp lý để giữ cho kích thước cam kết ít hơn kích thước bộ nhớ cache, nếu không sqlite sẽ bị buộc phải di chuyển nó trên đĩa. – Mash

6

Bạn có đang thực hiện INSERT của mỗi giao dịch mới dưới dạng Giao dịch cá nhân không?

Nếu bạn sử dụng BEGIN TRANSACTIONINSERT hàng theo hàng thì tôi nghĩ chỉ mục sẽ chỉ được tạo lại vào cuối mỗi Giao dịch.

+0

Nó sẽ. Tôi chỉ muốn đề nghị rằng quá :) –

+0

Có nhưng tôi có thể ép toàn bộ gigabyte thành một giao dịch không? Tôi gần như đã làm điều đó một cách tình cờ (quên đặt tuyên bố cam kết ở bất cứ đâu) và tôi nhận được một số lỗi đĩa I/O một nửa, mặc dù tôi không chắc chắn nếu nó liên quan ... –

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