質問

Question

1) I'm looking for an appropriate way to design a web application, and specifically the database schema, so that I can have a base table with all the core fields for a given service, and then depending on the type of service, I will need an additional set of fields to be associated with the service.

I need to do this in such a way that performing searches will be straight forward and offer reasonable performance. I'm probably looking at some type of full-text searching, but would only have 5 concurrent users of the application, at most.

My end goal for the application is to be able to pretty much search the entire database for any given keyword and return all related records. I was initially looking to split out the set fields for each service type into separate tables with their own columns, but I'm thinking that in doing so it might lead to more complicated search queries (Many JOINs) or many more queries to be run per search.

For any solution proposed, can you please specify why you think this would be a good fit?

2) My other issue (as will hopefully become clear below) is that my design currently consists of a "service types" table where I would define the core types of each product, where each service is then an "instance" of a given product.

My issue here is that it feels like I'll probably end up most duplicating things if I have both a products and a service types table. So to avoid this duplication is the other main thing I'm trying to achieve in my design.

More Details

I'm currently writing a custom web application used to track the services provisioned on a per-customer basis, not only for invoicing (billing cycle, start/end date, price) but also for documentation of those services (associated user accounts, IP addresses, physical assets, etc).

Each service is based off a "product" table which defines the name of a base product, the price, billing duration, description, etc... We could have multiple products of the same type (eg. For different plans of a given product type). For example, we have the following products:

  • Shared WebHosting Plan One
  • Shared WebHosting Plan Two
  • Shared WebHosting Plan Three
  • Dedicated Server Plan
  • Virtual Dedicated Server Plan One
  • Virtual Dedicated Server Plan Two

Right now the issue I have is that, we have a number of fields which are common to any given service, but we also have a number of fields which change, depending on the "type" of service being tracked. Depending on the type of the service, I will display the base form for all services, but also the appropriate form for adding/editing etc...

For example, we have the following service types, and each product (as shown above) would relate to one of these core service types:

  • Shared Web Hosting
  • Dedicated Hosting
  • Virtual Dedicated Hosting
  • ADSL
  • ...

My Possible Solutions

Current Solution - Multiple Tables

Currently, in my database, I have:

ServiceTypes

  • ServiceTypeID INT PK
  • Type VARCHAR(40)

Product

  • ProductID INT PK
  • Name VARCHAR(40)
  • Description TEXT
  • Price DECIMAL
  • BillingDuration INT
  • TypeID INT (FK ServiceTypes.ServiceTypeID)

Service

  • ServiceID INT PK
  • ProductID INT (FK: Product.ProductID)
  • Name VARCHAR(40)
  • Description TEXT
  • Price DECIMAL
  • BillingDuration INT
  • Active BIT
  • StartDate DATETIME
  • EndDate DATETIME

Those are the main tables for any service, then I've got additional tables for the extended properties:

ServiceADSLInfo

  • ServiceADSLInfoID INT PK
  • ServiceID INT (FK: Service.ServiceID)
  • FNN VARCHAR(10)
  • Username VARCHAR(20)
  • Password VARCHAR(20)
  • LocationID INT (FK: Locations.LocationID)
  • ModemAssetID INT (FK: Assets.AssetID)

ServiceVirtualServerInfo

  • ServiceVirtualServerInfo INT PK
  • ServiceID INT (FK: Service.ServiceID)
  • ServerName VARCHAR(20)
  • IPAddress INT (FK: IPAddresses.AddressID)
  • HostServer INT (FK: Assets.AssetID)
  • Username VARCHAR(20)
  • Password VARCHAR(20)

ServiceSharedHostingInfo

  • ServiceSharedHostingInfoID INT PK
  • ServiceID INT (FK: Service.ServiceID)
  • Hostname VARCHAR(50)
  • HostServer INT (FK: Assets.AssetID)
  • DiskSpaceQuota INT
  • BandwidthQuota INT

Other Solution - Single Table

I'm thinking of storing all service related information in a single table, regardless of the type of service, and just have the values be NULL if they're not needed for that particular service.

  • ServiceID INT PK
  • ProductID INT (FK: Product.ProductID)
  • Name VARCHAR(40)
  • Description TEXT
  • Price DECIMAL
  • BillingDuration INT
  • Active BIT
  • StartDate DATETIME
  • EndDate DATETIME
  • Username VARCHAR(20)
  • Password VARCHAR(20)
  • FNN VARCHAR(10)
  • LocationID INT (FK: Locations.LocationID)
  • AssetID INT (FK: Assets.AssetID)
  • ...

I feel like this might be an easier solution to work with in terms of searching as well, since in order to service any service related data, I can just use a full text search on the single table, and not worry about joining records together.

My main concern here would be that I end up with a table that has 30+ columns, which seems like it could get pretty messy. The other thing is that it doesn't solve both my concerns, because I would still need to have the core serviceTypes table to figure out which fields I need to use for any given search - and hence still have some overlap with my products table.

I'm wondering if some degree of overlap with the products table is impossible to avoid?

Entity-Attribute-Value model

I've considered this design as well. Overall, I feel like this is overkill for me as I don't need things to be that flexible and dynamic. We will need a set group of fields depending on the service type, but the data we need to collect on each core service type I can't see changing any time soon, so this can be static.

It also seems to me that the application logic needed to implement this level of flexibility would be far too complicated for the benefits it brings.

Having to determine the type of HTML form field to display depending on the type of the field queried from the database etc... Just sounds painful.

Please let me know if there are any further details I can provide! I hope everything is clear.

Thanks!

役に立ちましたか?

解決

i think this all depends on how you envisage moving forwards especially with new services comming into the system, all are valid approaches but all have pros and cons.

with the first approach you get a cleaner main table, but then for each service you have to create a seperate table, for new services you will have to continue doing this and for your application this may add some complexity as each service will need its own set of queries to pull the data (not sure what your architecture is here so is a stab in the dark. i personally feel this would hurt in the end.

the denormalized table approach would be easier to query, but then you may create a monster table with lots of unessary data for certain types. slightly different approach could be to add generic fields i.e. 10 fields called numX (where x is 1 to 10) that hold numbers, 10 called textx and so on, i think salesforce use this aporoach for custom fields for customers.

the key value field approach is like you say the most flexible, but you lose things like type recognition, everything needs to be the same type in the database at least.

it depends on the nature of your app, performance for 5 concurrent users should not be the concern, so maybe ease of implementation should be. the generic approach outlines (the sales force approach) might work here and possibly cover you for other services moving forwards and future proof you a little, but it depends on how much change you envisage.

if change is going to be consistent, loads if services with different fields etc thw the key/value approach is probably your best bet, but at that stage you could also look at some nosql approaches as they may fit the bill here, but mysql would still work, just opening up the discussion.

Update

to go along with the comment, if you don't envisage change too frequently with the services, i would skip noSQL, as it will add complexity to your development that probably wont benefit you.

As stated the types of services probably wont change too much then i think the denormalized, generic approach might work for you. This way you application can have one area for services, and you can treat additional properties as "custom fields" and add as appropriate. that way you app is generic. One unfortunate side effect is you will have to manage that in your application somehow through some logic to test if it there or not, and you will have to pull all the fields regardless if they are populated or not, for your needs currently, probably not a huge tradeoff.

A sample (very very simple) example of the generic approach.

enter image description here

  • Generic fields being your mainstay fields that are shared across all services.

This could make searching a bit of a pain, as you may (depending on the mechanism) have to include all fields in the search

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top