views:

211

answers:

2

Trying to recreate my SQL Server database on PostgreSQL. Everything is ok except I can't find how to recreate this index:

USE [mytablename]  
GO  
CREATE NONCLUSTERED INDEX [myindex]  
ON [dbo].[mytablename] ([col1],[col2])  
INCLUDE ([col3],[col4])  
GO

Will be very grateful for help.

Alexey

Update:

http://img38.imageshack.us/img38/1071/89013974.png here is db structure star+eav
there is only one query

SELECT this_.id as id0_0_,   
this_.device_id as device2_0_0_,  
this_.time_id as time3_0_0_,  
this_.gps_detail_id as gps4_0_0_   
FROM [scoutserver_data].[dbo].[DataMessage]  this_   
WHERE this_.time_id = 65536 and this_.device_id = 32768

Maybe it is not optimal atm. And im working on it also. Maybe something like this

SELECT * FROM [scoutserver_data].[dbo].[TimeDimension]   
  INNER JOIN ([scoutserver_data].[dbo].[DeviceDimension]   
  INNER JOIN  [scoutserver_data].[dbo].[DataMessage]   
ON [DeviceDimension].[device_id] =[DataMessage].[device_id])  
ON [TimeDimension].[time_id] = [DataMessage].[time_id]  
WHERE DeviceDimension.serial_id='2' AND TimeDimension.Day=15 AND TimeDimension.Year=2009

Any hints welcome =)

+1  A: 
CREATE INDEX myindex ON mytablename (co1l, col2, col3, col4)

PostgreSQL does not support clustered or covering indexes.

Update:

For this query, you'll need to create the suggested index indeed:

SELECT  this_.id as id0_0_,   
        this_.device_id as device2_0_0_,  
        this_.time_id as time3_0_0_,  
        this_.gps_detail_id as gps4_0_0_   
FROM    DataMessage this_   
WHERE   this_.time_id = 65536
        AND this_.device_id = 32768

CREATE INDEX ix_datamessage_time_device_id_detail ON datamessage (time_id, device_id, id, gps_detail_id)

However, your tables seem to be over-normalized to me.

You can keep year, month and day in a single INT field in your table. This will save you a join.

There might be the point of keeping DataMessage and GpsDetails in separate tables if either GpsDetails are rarely linked to the DataMessage (this is, gps_details_id is often set to NULL), or a GPS details record can be shared between multiple data messages.

It it's not, it will be better to move the GPS details into the data messages table.

Quassnoi
Thanks, is there any guideline for indexin HUGE tables in PG?
Alexey Anufriyev
An index will hamper `DML` performance and speed up sargable queries. It's hard to tell unless I see your table structure and the queries.
Quassnoi
Well, there's always http://www.postgresql.org/docs/8.4/static/indexes-multicolumn.html
Kev
I have separated timedimension table to query diffirent chunks of messages. Also this data will be used in reporting. Inserts are going to be once a day. Operational data wich is not persisted in db - is stored in hdd cache and aggregated before writes. On MSSQL im getting 17k data from 15gb datamessage table in 15ms. Trying to achive same thing on postgresql. GpsDetail is nullable because datamessage doesnot contain it every time. And MessageData is going to be huge - 50+Gb on single table.
Alexey Anufriyev
Create the index on all four columns then, as described in the post. This is almost the same as a covering index in `SQL Server` except that the `id` and `gps_detail_id` are a part of the index key, not the index data. This only matters for `DML` and key lookup time a little. Range scan will be the same. Note, however, that `PostgreSQL` is much more slow in traversing the indexes than `SQL Server`.
Quassnoi
thanks a lot, anyway PostgreSQL is targeted for customers with small IT budgets and lower loads. For other customers we provide Oracle and MSSQL solutions.
Alexey Anufriyev
Partitioning over the time dimension is the usual approach to managing huge tables in Postgresql.
Ants Aasma
A: 

http://img38.imageshack.us/img38/1071/89013974.png here is db structure star+eav
there is only one query

SELECT this_.id as id0_0_,   
this_.device_id as device2_0_0_,  
this_.time_id as time3_0_0_,  
this_.gps_detail_id as gps4_0_0_   
FROM [scoutserver_data].[dbo].[DataMessage]  this_   
WHERE this_.time_id = 65536 and this_.device_id = 32768

Maybe it is not optimal atm. And im working on it also. Maybe something like this

SELECT * FROM [scoutserver_data].[dbo].[TimeDimension]   
  INNER JOIN ([scoutserver_data].[dbo].[DeviceDimension]   
  INNER JOIN  [scoutserver_data].[dbo].[DataMessage]   
ON [DeviceDimension].[device_id] =[DataMessage].[device_id])  
ON [TimeDimension].[time_id] = [DataMessage].[time_id]  
WHERE DeviceDimension.serial_id='2' AND TimeDimension.Day=15 AND TimeDimension.Year=2009

Any hints welcome=)

Alexey Anufriyev
Please post clarifications as the edits to the question, not as the answer. Thanks.
Quassnoi
600 characters wan not enougth=( sorry for this
Alexey Anufriyev
No, not as a comment--click the edit link above it and change the question to include more details.
Kev
ops my bad=) will do this in future posts
Alexey Anufriyev