2010-11-07 28 views
6

Giả sử rằng tôi có một bảng lớn với ba cột: "user_name", "user_property", "value_of_property". Lat cũng giả định rằng tôi có rất nhiều người dùng (giả sử 100 000) và rất nhiều thuộc tính (giả sử 10 000). Sau đó, bảng sẽ là rất lớn (1 tỷ hàng).Tôi có thể tối ưu hóa cơ sở dữ liệu của mình bằng cách tách một bảng lớn thành nhiều bảng nhỏ không?

Khi tôi trích xuất thông tin từ bảng tôi luôn luôn cần thông tin về một người dùng cụ thể. Vì vậy, tôi sử dụng, ví dụ: where user_name='Albert Gates'. Vì vậy, mỗi khi máy chủ mysql cần phân tích 1 tỷ dòng để tìm những người trong số họ có chứa "Albert Gates" như user_name.

có nó không được khôn ngoan để phân chia các bảng lớn thành nhiều những cái nhỏ tương ứng với người dùng cố định?

+0

những gì bạn mô tả được gọi là phân vùng. Trong cơ sở dữ liệu bạn thiết kế cấu trúc rtable xung quanh dữ liệu của bạn. Bạn thiết lập phần cứng để quản lý loại sự cố này. Tôi tin rằng parttioning (đó là máy chủ sql lingo cho những gì bạn đang nói về) là một tính năng mà không phải là trong mysql - hoặc nó đã không được 7 năm trước khi tôi chuyển sang máy chủ sql - mà tôi biết không hỗ trợ nó. –

+0

@ John Nicholas: http://dev.mysql.com/doc/refman/5.1/en/partitioning.html –

+0

coool tyvm;) mysql có phân vùng afterall –

Trả lời

5

Không, tôi không nghĩ đó là một ý tưởng hay. Một cách tiếp cận tốt hơn là để add an index trên cột user_name - và có lẽ một chỉ mục khác trên (user_name, user_property) để tìm kiếm một thuộc tính duy nhất. Sau đó, cơ sở dữ liệu không cần phải quét tất cả các hàng - nó chỉ cần tìm mục thích hợp trong chỉ mục được lưu trữ trong một B-Tree, giúp bạn dễ dàng tìm thấy một bản ghi trong một khoảng thời gian rất ngắn.

Nếu ứng dụng của bạn vẫn còn chậm ngay cả sau khi lập chỉ mục chính xác, đôi khi có thể là một ý tưởng hay cho partition bảng lớn nhất của bạn.

Một điều khác mà bạn có thể xem xét là bình thường hóa cơ sở dữ liệu của bạn để user_name được lưu trữ trong một bảng riêng biệt và sử dụng một chìa khóa foriegn số nguyên trong vị trí của nó. Điều này có thể làm giảm yêu cầu lưu trữ và có thể tăng hiệu suất. Điều tương tự cũng có thể áp dụng cho user_property.

+0

lợi thế khác của việc chuẩn hóa user_name và sử dụng id của nó trong các bảng khác là nếu bạn cần thay đổi nó, bạn không phải cập nhật hàng nghìn bản ghi và tất cả các mối quan hệ của chúng. –

3

bạn nên bình thường thiết kế của bạn như sau:

drop table if exists users; 
create table users 
(
user_id int unsigned not null auto_increment primary key, 
username varbinary(32) unique not null 
) 
engine=innodb; 

drop table if exists properties; 
create table properties 
(
property_id smallint unsigned not null auto_increment primary key, 
name varchar(255) unique not null 
) 
engine=innodb; 

drop table if exists user_property_values; 
create table user_property_values 
(
user_id int unsigned not null, 
property_id smallint unsigned not null, 
value varchar(255) not null, 
primary key (user_id, property_id), 
key (property_id) 
) 
engine=innodb; 

insert into users (username) values ('f00'),('bar'),('alpha'),('beta'); 

insert into properties (name) values ('age'),('gender'); 

insert into user_property_values values 
(1,1,'30'),(1,2,'Male'), 
(2,1,'24'),(2,2,'Female'), 
(3,1,'18'), 
(4,1,'26'),(4,2,'Male'); 

Từ góc độ hiệu suất chỉ số InnoDB cụm công trình kỳ diệu trong ví dụ tương tự này (COLD chạy):

select count(*) from product 
count(*) 
======== 
1,000,000 (1M) 

select count(*) from category 
count(*) 
======== 
250,000 (500K) 

select count(*) from product_category 
count(*) 
======== 
125,431,192 (125M) 

select 
c.*, 
p.* 
from 
product_category pc 
inner join category c on pc.cat_id = c.cat_id 
inner join product p on pc.prod_id = p.prod_id 
where 
pc.cat_id = 1001; 
0:00:00.030: Query OK (0.03 secs) 
+0

xin vui lòng bình luận nếu bạn bỏ phiếu nếu không bạn chỉ chứng minh sự thiếu hiểu biết của mình. –

+0

Tôi không nghĩ rằng bạn đã chuẩn hóa mọi thứ. Điều gì đã được chuẩn hóa? Thứ tự bình thường là gì? Sự lặp lại của dữ liệu đã được loại bỏ? Ngoài ra (và đây là nit picky, tôi xin lỗi), nơi bạn sẽ lưu trữ giá trị của tài sản? Bạn có thực sự muốn các tài sản để hav ea nhiều đến nhiều mối quan hệ? Hiện tại, mỗi thuộc tính có thể được chia sẻ giữa nhiều người dùng và sẽ rất khó có các thuộc tính bắt buộc. –

+0

xin lỗi tôi đã xóa nó trong khi tôi phản ánh. –

1

Tại sao bạn cần phải có cấu trúc bảng này. Vấn đề gây quỹ của tôi là bạn sẽ phải truyền dữ liệu theo giá trị của bất động sản mỗi lần bạn muốn sử dụng nó. Đó là xấu trong quan điểm của tôi - cũng lưu trữ số như văn bản là điên cho rằng tất cả nhị phân của nó anyway. Ví dụ, bạn sẽ có các trường bắt buộc như thế nào? Hoặc các trường cần phải có các ràng buộc dựa trên các trường khác? Ví dụ: ngày bắt đầu và ngày kết thúc?

Tại sao không chỉ cần có các thuộc tính như các lĩnh vực chứ không phải là một số nhiều mối quan hệ?

có 1 bàn phẳng. Khi quy tắc kinh doanh của bạn bắt đầu cho thấy rằng các thuộc tính nên được nhóm lại, bạn có thể xem xét di chuyển chúng ra thành các bảng khác và có một số mối quan hệ 1: 0-1 với bảng người dùng. Nhưng đây không phải là bình thường hóa và nó sẽ làm giảm hiệu suất một chút do sự tham gia thêm (tuy nhiên bản chất tự viết tư liệu của các tên bảng sẽ hỗ trợ rất nhiều cho bất kỳ nhà phát triển nào)

Một cách tôi thường xuyên thấy hiệu suất databqase hoàn toàn bị thiến là có một Id

generic, Loại bất động sản, tài sản Tên, bảng Property Value.

Điều này thực sự rất lười nhưng đặc biệt linh hoạt nhưng hoàn toàn giết chết hiệu suất. Trong thực tế trên một công việc mới, nơi hiệu suất là xấu tôi thực sự yêu cầu nếu họ có một bảng với cấu trúc này - nó luôn luôn trở thành điểm trung tâm của cơ sở dữ liệu và là chậm.Toàn bộ quan điểm của thiết kế cơ sở dữ liệu quan hệ là các mối quan hệ được xác định trước thời hạn. Đây chỉ đơn giản là một kỹ thuật nhằm tăng tốc độ phát triển với chi phí rất lớn cho tốc độ ứng dụng. Nó cũng đặt một sự phụ thuộc rất lớn vào logic nghiệp vụ trong lớp ứng dụng để hành xử - mà không phải là phòng thủ chút nào. Cuối cùng bạn thấy rằng bạn wan để sử dụng tài sản trong một quan hệ quan trọng dẫn đến tất cả các loại đúc trên tham gia mà tiếp tục làm suy giảm hiệu suất.

Nếu dữ liệu có mối quan hệ 1: 1 với một thực thể thì đó phải là trường trên cùng một bảng. Nếu bảng của bạn được nhiều hơn 30 trường rộng, sau đó xem xét di chuyển chúng vào một bảng khác nhưng không gọi nó là bình thường hóa vì nó không phải là. Đây là một kỹ thuật để giúp các nhà phát triển nhóm các lĩnh vực với nhau tại các chi phí của hiệu suất trong một nỗ lực để hỗ trợ sự hiểu biết.

Tôi không biết nếu mysql có tương đương nhưng sqlserver 2008 có cột thưa thớt - giá trị null không chiếm không gian. SParse column datatypes

Tôi không nói phương pháp EAV luôn sai, nhưng tôi nghĩ rằng việc sử dụng cơ sở dữ liệu quan hệ cho phương pháp này có lẽ không phải là lựa chọn tốt nhất.

2

Việc lập chỉ mục đúng cơ sở dữ liệu của bạn sẽ là cách số 1 để cải thiện hiệu suất. Tôi đã từng có một truy vấn mất một nửa giờ (trên một tập dữ liệu lớn, nhưng không có ít hơn). Sau đó, chúng tôi đến để tìm hiểu rằng các bảng không có chỉ mục. Sau khi lập chỉ mục truy vấn mất chưa tới 10 giây.

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